@lunora/runtime 1.0.0-alpha.31 → 1.0.0-alpha.32

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/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
+ import { R2SqlClient } from '@lunora/bindings/r2sql';
1
2
  import { RankDirection, RankPageRow, DatabaseWriterLike } from '@lunora/do';
2
3
  export type { RankDirection as RankPageDirection, RankPageRowKey as RankPageKey, RankPageRow, ShardRankPageResult } from '@lunora/do';
3
4
  import { WorkflowsRestClient } from '@lunora/workflow';
4
5
  import { LunoraError as LunoraError$1, ErrorBody } from '@lunora/errors';
5
- import { R2SqlClient } from '@lunora/bindings/r2sql';
6
6
  /**
7
7
  * Turn-key incremental-sync source helpers for warehouse connectors
8
8
  * (Fivetran custom functions, Airbyte incremental sources).
@@ -662,6 +662,172 @@ interface LogEvent {
662
662
  /** Acting userId, or absent when anonymous. */
663
663
  userId?: string;
664
664
  }
665
+ /**
666
+ * The written-column contract: every field `pipelineLogSink` emits, mapped to the
667
+ * column it is stored under by default (the identity mapping). Also the source of
668
+ * truth for the {@link PipelineLogField} union. Mirrors the record built in
669
+ * `pipelineLogSink` — the read side of the same contract.
670
+ */
671
+ declare const DEFAULT_COLUMNS: {
672
+ readonly fields: "fields";
673
+ readonly functionPath: "functionPath";
674
+ readonly level: "level";
675
+ readonly message: "message";
676
+ readonly shardKey: "shardKey";
677
+ readonly spanId: "spanId";
678
+ readonly traceId: "traceId";
679
+ readonly ts: "ts";
680
+ readonly userId: "userId";
681
+ };
682
+ /**
683
+ * The canonical field names of one persisted log record — the keys
684
+ * `pipelineLogSink` writes. Used as the {@link PipelineLogColumnMap} keys and the
685
+ * {@link PipelineLogRow} shape, so the reader stays decoupled from whatever
686
+ * physical column names the operator's Iceberg table happens to use.
687
+ */
688
+ type PipelineLogField = keyof typeof DEFAULT_COLUMNS;
689
+ /**
690
+ * Field-to-column-name map. Defaults to the identity mapping (each field stored
691
+ * under its own name, matching what `pipelineLogSink` writes). Override per-field
692
+ * when the Iceberg schema renames a column; unspecified fields keep their
693
+ * default. This is the single knob that lets one reader serve differently shaped
694
+ * Data Catalog tables.
695
+ */
696
+ type PipelineLogColumnMap = Partial<Record<PipelineLogField, string>>;
697
+ /** An opaque keyset cursor: the `ts` of the row after the last one returned. */
698
+ interface PipelineLogCursor {
699
+ /** Epoch-millis boundary; the next page is every row strictly older than this. */
700
+ ts: number;
701
+ }
702
+ /** Filters for one {@link PipelineLogReader} query. Every value is inlined safely (`lit`/`sql`). */
703
+ interface PipelineLogQuery {
704
+ /** Continue after a previous page (keyset on `ts DESC`). Combined with the other filters. */
705
+ cursor?: PipelineLogCursor;
706
+ /** Match only this exact function path's records. Prefer `functionPathPrefix` for a namespace sweep. */
707
+ functionPath?: string;
708
+ /** Match records whose `functionPath` starts with this string (rendered as a `LIKE 'prefix%'`). */
709
+ functionPathPrefix?: string;
710
+ /** Match only this exact severity. When set, `minLevel` is ignored for the same field. */
711
+ level?: ContextLogLevel;
712
+ /** Max rows to return. Clamped to `[1, 10000]`; defaults to {@link DEFAULT_LOG_LIMIT}. */
713
+ limit?: number;
714
+ /** Severity floor: keep every level at or above this in {@link LOG_LEVEL_ORDER} (e.g. `warn` keeps warn, error, fatal). */
715
+ minLevel?: ContextLogLevel;
716
+ /** Match only this shard key. */
717
+ shardKey?: string;
718
+ /** Lower time bound, inclusive (`ts` at or after this), epoch-millis. */
719
+ sinceTs?: number;
720
+ /** Match only this trace id. */
721
+ traceId?: string;
722
+ /** Upper time bound, inclusive (`ts` at or before this), epoch-millis. */
723
+ untilTs?: number;
724
+ /** Match only this acting user id. */
725
+ userId?: string;
726
+ }
727
+ /**
728
+ * One decoded log record. Always keyed by the canonical {@link PipelineLogField}
729
+ * names regardless of the physical columns (the reader remaps via `columnMap`),
730
+ * so consumers never see the operator's storage names.
731
+ */
732
+ interface PipelineLogRow {
733
+ /**
734
+ * Structured fields, when the record carried them. A `serializeFields` sink
735
+ * stores these as a JSON string, which the reader parses back to an object;
736
+ * a plain string that is not valid JSON is returned verbatim.
737
+ */
738
+ fields?: unknown;
739
+ /** Function path that emitted the line, e.g. `"messages:list"`. */
740
+ functionPath: string;
741
+ /** Severity the line was logged at. */
742
+ level: ContextLogLevel;
743
+ /** Rendered message. */
744
+ message: string;
745
+ /** Shard key for single-shard calls, when present. */
746
+ shardKey?: string;
747
+ /** Span id the line was emitted under, when present. */
748
+ spanId?: string;
749
+ /** Trace id the line belongs to, when present. */
750
+ traceId?: string;
751
+ /** Epoch-millis the line was emitted. */
752
+ ts: number;
753
+ /** Acting user id, when present. */
754
+ userId?: string;
755
+ }
756
+ /** One page of {@link PipelineLogRow}s, newest first, plus the cursor for the next page (absent means last page). */
757
+ interface PipelineLogPage {
758
+ /** The cursor to pass as {@link PipelineLogQuery} `cursor` for the following page; absent when this is the last page. */
759
+ nextCursor?: PipelineLogCursor;
760
+ /** The rows, ordered `ts DESC` (newest first). At most `limit` of them. */
761
+ rows: PipelineLogRow[];
762
+ }
763
+ /** Options for {@link createPipelineLogReader}. */
764
+ interface PipelineLogReaderOptions {
765
+ /**
766
+ * Override any physical column name that diverges from the default (identity)
767
+ * mapping. Unspecified fields keep their {@link DEFAULT_LOG_COLUMNS} name.
768
+ */
769
+ columnMap?: PipelineLogColumnMap;
770
+ /**
771
+ * The Iceberg namespace the `table` lives in (R2 Data Catalog database).
772
+ * Combined as `namespace.table` in the `FROM` clause; omit when `table`
773
+ * already carries its namespace.
774
+ */
775
+ namespace?: string;
776
+ /** The Iceberg table name the Pipeline writes log records to (e.g. `"logs"`). */
777
+ table: string;
778
+ }
779
+ /** The reader surface: a single keyset-paginated {@link PipelineLogPage} query. */
780
+ interface PipelineLogReader {
781
+ /** Run one filtered, keyset-paginated read and return a {@link PipelineLogPage}. */
782
+ query: (query?: PipelineLogQuery) => Promise<PipelineLogPage>;
783
+ }
784
+ /** The written-column contract exposed publicly: canonical field to default physical column name. */
785
+ declare const DEFAULT_LOG_COLUMNS: Readonly<Record<PipelineLogField, string>>;
786
+ /** Default page size when a query omits `limit`. */
787
+ declare const DEFAULT_LOG_LIMIT: number;
788
+ /**
789
+ * Build a durable-log reader over one R2 Data Catalog (Iceberg) table.
790
+ *
791
+ * The returned {@link PipelineLogReader} compiles each call to a safe
792
+ * `SELECT ... WHERE ... ORDER BY ts DESC LIMIT n` (over-fetching by one) and
793
+ * decodes the rows back to the canonical {@link PipelineLogRow} shape. All value
794
+ * filters are escaped through `@lunora/bindings/r2sql`'s `sql`/`lit`; column
795
+ * names come from `options.columnMap` (operator config), spliced with `raw`.
796
+ * @param client An {@link R2SqlClient} (`createR2Sql({ accountId, apiToken, bucket })`).
797
+ * @param options The target `table` (plus optional `namespace`) and any `columnMap` overrides.
798
+ */
799
+ declare const createPipelineLogReader: (client: R2SqlClient, options: PipelineLogReaderOptions) => PipelineLogReader;
800
+ /**
801
+ * Wire constants for the durable log archive, shared between the server route
802
+ * (`@lunora/runtime`'s `log-archive-admin-routes`) and the Studio Archive feed
803
+ * (`@lunora/studio`). Kept here — not in `@lunora/runtime` — because the studio
804
+ * is a browser bundle that must not import a runtime *value* (which would drag
805
+ * the DO/R2-SQL runtime into the browser). This file is dependency-free and
806
+ * bundler-inlined into each consumer, so both sides share one source of truth
807
+ * with no dependency edge.
808
+ */
809
+ /**
810
+ * The error `code` the archive route returns (400) when the operator has wired
811
+ * no archive table (`logArchive`) or the `R2_SQL_*` credentials are missing. The
812
+ * Studio keys its "not configured" empty state off this exact value.
813
+ */
814
+ declare const LOG_ARCHIVE_NOT_CONFIGURED = "LOG_ARCHIVE_NOT_CONFIGURED";
815
+ /** The route the studio's `queryLogArchive` client method POSTs to. */
816
+ declare const LOG_ARCHIVE_PATH = "/_lunora/admin/logs/archive";
817
+ /**
818
+ * The app-level archive config the worker passes through: which Data Catalog
819
+ * table the Pipeline writes log records to (the read-side of `pipelineLogSink`),
820
+ * plus optional namespace / physical-column overrides. The R2 SQL *credentials*
821
+ * are NOT here — they live on `env` (`R2_SQL_*`), read per request.
822
+ */
823
+ interface LogArchiveConfig {
824
+ /** Override any physical column name that diverges from the {@link createPipelineLogReader} default mapping. */
825
+ columnMap?: PipelineLogColumnMap;
826
+ /** The Iceberg namespace (R2 Data Catalog database) the table lives in; omit when `table` already carries it. */
827
+ namespace?: string;
828
+ /** The Iceberg table the Pipeline writes log records to (e.g. `"logs"`). */
829
+ table: string;
830
+ }
665
831
  /**
666
832
  * What kind of instrument produced a measurement, which decides how a collector
667
833
  * aggregates it:
@@ -2275,6 +2441,15 @@ interface WorkerOptions {
2275
2441
  * Omit it and those endpoints respond `KV_NOT_CONFIGURED`.
2276
2442
  */
2277
2443
  kvIntrospector?: KvIntrospector;
2444
+ /**
2445
+ * The durable log archive's read config — the R2 Data Catalog (Iceberg)
2446
+ * table `pipelineLogSink` writes to, so the studio Logs panel's Archive feed
2447
+ * (and the `/_lunora/admin/logs/archive` route) can read it back via R2 SQL.
2448
+ * The R2 SQL credentials come from `env` (`R2_SQL_ACCOUNT_ID` / `R2_SQL_TOKEN`
2449
+ * / `R2_SQL_BUCKET`); this only names the table (+ optional namespace / column
2450
+ * overrides). Absent → the Archive feed reports "not configured".
2451
+ */
2452
+ logArchive?: LogArchiveConfig;
2278
2453
  /**
2279
2454
  * Optional telemetry sink. When supplied, the worker emits one
2280
2455
  * `onRpc` event per dispatched RPC (single-shard forward or fan-out)
@@ -3037,140 +3212,5 @@ declare const otlpSink: (options: OtlpSinkOptions) => ObservabilitySink;
3037
3212
  * @param sinks The sinks to fan out to.
3038
3213
  */
3039
3214
  declare const combineSinks: (...sinks: ObservabilitySink[]) => ObservabilitySink;
3040
- /**
3041
- * The written-column contract: every field `pipelineLogSink` emits, mapped to the
3042
- * column it is stored under by default (the identity mapping). Also the source of
3043
- * truth for the {@link PipelineLogField} union. Mirrors the record built in
3044
- * `pipelineLogSink` — the read side of the same contract.
3045
- */
3046
- declare const DEFAULT_COLUMNS: {
3047
- readonly fields: "fields";
3048
- readonly functionPath: "functionPath";
3049
- readonly level: "level";
3050
- readonly message: "message";
3051
- readonly shardKey: "shardKey";
3052
- readonly spanId: "spanId";
3053
- readonly traceId: "traceId";
3054
- readonly ts: "ts";
3055
- readonly userId: "userId";
3056
- };
3057
- /**
3058
- * The canonical field names of one persisted log record — the keys
3059
- * `pipelineLogSink` writes. Used as the {@link PipelineLogColumnMap} keys and the
3060
- * {@link PipelineLogRow} shape, so the reader stays decoupled from whatever
3061
- * physical column names the operator's Iceberg table happens to use.
3062
- */
3063
- type PipelineLogField = keyof typeof DEFAULT_COLUMNS;
3064
- /**
3065
- * Field-to-column-name map. Defaults to the identity mapping (each field stored
3066
- * under its own name, matching what `pipelineLogSink` writes). Override per-field
3067
- * when the Iceberg schema renames a column; unspecified fields keep their
3068
- * default. This is the single knob that lets one reader serve differently shaped
3069
- * Data Catalog tables.
3070
- */
3071
- type PipelineLogColumnMap = Partial<Record<PipelineLogField, string>>;
3072
- /** An opaque keyset cursor: the `ts` of the row after the last one returned. */
3073
- interface PipelineLogCursor {
3074
- /** Epoch-millis boundary; the next page is every row strictly older than this. */
3075
- ts: number;
3076
- }
3077
- /** Filters for one {@link PipelineLogReader} query. Every value is inlined safely (`lit`/`sql`). */
3078
- interface PipelineLogQuery {
3079
- /** Continue after a previous page (keyset on `ts DESC`). Combined with the other filters. */
3080
- cursor?: PipelineLogCursor;
3081
- /** Match only this exact function path's records. Prefer `functionPathPrefix` for a namespace sweep. */
3082
- functionPath?: string;
3083
- /** Match records whose `functionPath` starts with this string (rendered as a `LIKE 'prefix%'`). */
3084
- functionPathPrefix?: string;
3085
- /** Match only this exact severity. When set, `minLevel` is ignored for the same field. */
3086
- level?: ContextLogLevel;
3087
- /** Max rows to return. Clamped to `[1, 10000]`; defaults to {@link DEFAULT_LOG_LIMIT}. */
3088
- limit?: number;
3089
- /** Severity floor: keep every level at or above this in {@link LOG_LEVEL_ORDER} (e.g. `warn` keeps warn, error, fatal). */
3090
- minLevel?: ContextLogLevel;
3091
- /** Match only this shard key. */
3092
- shardKey?: string;
3093
- /** Lower time bound, inclusive (`ts` at or after this), epoch-millis. */
3094
- sinceTs?: number;
3095
- /** Match only this trace id. */
3096
- traceId?: string;
3097
- /** Upper time bound, inclusive (`ts` at or before this), epoch-millis. */
3098
- untilTs?: number;
3099
- /** Match only this acting user id. */
3100
- userId?: string;
3101
- }
3102
- /**
3103
- * One decoded log record. Always keyed by the canonical {@link PipelineLogField}
3104
- * names regardless of the physical columns (the reader remaps via `columnMap`),
3105
- * so consumers never see the operator's storage names.
3106
- */
3107
- interface PipelineLogRow {
3108
- /**
3109
- * Structured fields, when the record carried them. A `serializeFields` sink
3110
- * stores these as a JSON string, which the reader parses back to an object;
3111
- * a plain string that is not valid JSON is returned verbatim.
3112
- */
3113
- fields?: unknown;
3114
- /** Function path that emitted the line, e.g. `"messages:list"`. */
3115
- functionPath: string;
3116
- /** Severity the line was logged at. */
3117
- level: ContextLogLevel;
3118
- /** Rendered message. */
3119
- message: string;
3120
- /** Shard key for single-shard calls, when present. */
3121
- shardKey?: string;
3122
- /** Span id the line was emitted under, when present. */
3123
- spanId?: string;
3124
- /** Trace id the line belongs to, when present. */
3125
- traceId?: string;
3126
- /** Epoch-millis the line was emitted. */
3127
- ts: number;
3128
- /** Acting user id, when present. */
3129
- userId?: string;
3130
- }
3131
- /** One page of {@link PipelineLogRow}s, newest first, plus the cursor for the next page (absent means last page). */
3132
- interface PipelineLogPage {
3133
- /** The cursor to pass as {@link PipelineLogQuery} `cursor` for the following page; absent when this is the last page. */
3134
- nextCursor?: PipelineLogCursor;
3135
- /** The rows, ordered `ts DESC` (newest first). At most `limit` of them. */
3136
- rows: PipelineLogRow[];
3137
- }
3138
- /** Options for {@link createPipelineLogReader}. */
3139
- interface PipelineLogReaderOptions {
3140
- /**
3141
- * Override any physical column name that diverges from the default (identity)
3142
- * mapping. Unspecified fields keep their {@link DEFAULT_LOG_COLUMNS} name.
3143
- */
3144
- columnMap?: PipelineLogColumnMap;
3145
- /**
3146
- * The Iceberg namespace the `table` lives in (R2 Data Catalog database).
3147
- * Combined as `namespace.table` in the `FROM` clause; omit when `table`
3148
- * already carries its namespace.
3149
- */
3150
- namespace?: string;
3151
- /** The Iceberg table name the Pipeline writes log records to (e.g. `"logs"`). */
3152
- table: string;
3153
- }
3154
- /** The reader surface: a single keyset-paginated {@link PipelineLogPage} query. */
3155
- interface PipelineLogReader {
3156
- /** Run one filtered, keyset-paginated read and return a {@link PipelineLogPage}. */
3157
- query: (query?: PipelineLogQuery) => Promise<PipelineLogPage>;
3158
- }
3159
- /** The written-column contract exposed publicly: canonical field to default physical column name. */
3160
- declare const DEFAULT_LOG_COLUMNS: Readonly<Record<PipelineLogField, string>>;
3161
- /** Default page size when a query omits `limit`. */
3162
- declare const DEFAULT_LOG_LIMIT: number;
3163
- /**
3164
- * Build a durable-log reader over one R2 Data Catalog (Iceberg) table.
3165
- *
3166
- * The returned {@link PipelineLogReader} compiles each call to a safe
3167
- * `SELECT ... WHERE ... ORDER BY ts DESC LIMIT n` (over-fetching by one) and
3168
- * decodes the rows back to the canonical {@link PipelineLogRow} shape. All value
3169
- * filters are escaped through `@lunora/bindings/r2sql`'s `sql`/`lit`; column
3170
- * names come from `options.columnMap` (operator config), spliced with `raw`.
3171
- * @param client An {@link R2SqlClient} (`createR2Sql({ accountId, apiToken, bucket })`).
3172
- * @param options The target `table` (plus optional `namespace`) and any `columnMap` overrides.
3173
- */
3174
- declare const createPipelineLogReader: (client: R2SqlClient, options: PipelineLogReaderOptions) => PipelineLogReader;
3175
3215
  declare const VERSION: string;
3176
- export { type AdminTableResolver, type AirbyteMessage, type AnalyticsEngineDataPointLike, type AnalyticsEngineDatasetLike, type AnalyticsEngineSinkOptions, type AuthAdmin, type AuthCapabilities, type AuthConfigInfo, type AuthImpersonation, type AuthPage, type AuthSession, type AuthUser, type AuthUserFieldSpec, type BackupManifest, type BackupStore, type ComposeIdentityResolversErrorMode, type ComposeIdentityResolversOptions, type ConnectorChange, type ConnectorSyncPage, type CorsOptions, type CronHandler, type CronJobDispatch, type CronJobInfo, type CrossShardCounter, type CrossShardReader, type CrossShardRelationCapabilities, type CrossShardRelationOptions, type CsrfOptions, DEFAULT_LOG_COLUMNS, DEFAULT_LOG_LIMIT, DEFAULT_REGISTRY_CACHE_TTL_MS, type DurableObjectJurisdiction, type DynamicShardRegistry, type DynamicShardRegistryOptions, type ExecutionContextLike, type ExportFanOutRequest, type ExportFanOutResult, type FanOutRequest, type FanOutResult, type FanOutSpec, type FivetranResponse, type FrameworkHostHandler, type FrameworkWorkerOptions, type FrameworkWorkerOptionsInput, type FunctionDescriptor, type FunctionRegistryEntry, type FunctionRegistryLike, type GlobalExportFunction as GlobalExportFn, type GlobalImportFunction as GlobalImportFn, type GlobalIntrospector, type GlobalTableInfo as GlobalTableInfoMeta, type GlobalTablePage as GlobalTablePageMeta, type HttpActionContext, type HttpActionLike, type HttpRouterLike, type IdentityContractLike, type IdentityResolver, type IdentityValidation, type ImportFanOutRequest, type ImportFanOutResult, type KvIntrospector, type KvKeyEntry, type KvKeyListResult, type KvNamespaceSummary, type KvValueResult, type ListAuthUsersOptions, type LogEvent, type LogFields, type LogLevel, LunoraError, type LunoraErrorBody, type LunoraHandlerOptions, type LunoraWorker, type MergeStrategy, type MetricEvent, type MetricKind, type MigrationFanOutRequest, type MigrationFanOutResult, NOOP_EXECUTION_CONTEXT, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type OtlpSinkOptions, type PipelineLike, type PipelineLogColumnMap, type PipelineLogCursor, type PipelineLogField, type PipelineLogPage, type PipelineLogQuery, type PipelineLogReader, type PipelineLogReaderOptions, type PipelineLogRow, type PipelineLogSinkOptions, type QueryCoordinator, type QueryCoordinatorOptions, type RankFanOutRequest, type RankFanOutResult, type RankPageFanOutRequest, type RankPageFanOutResult, type ResolvedSecurity, type ResolvedShard, type Route, type RpcContext, type RpcEnvelope, SHARD_REGISTRY_DO_NAME, type ScheduledControllerLike, type SecurityHeadersOptions, type SecurityOptions, type SentrySinkOptions, type ShardError, type ShardExportOutcome, type ShardImportOutcome, type ShardMigrationOutcome, type ShardNamespaceLike, type ShardRankOutcome, type ShardRankPageOutcome, type ShardRegistry, type ShardTrafficEntry, type ShardTrafficFanOutRequest, type ShardTrafficFanOutResult, type ShardingInfo, type SpanEvent, type StorageListFunction as StorageListFn, type StorageObject, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createLunoraHandler, createPipelineLogReader, createQueryCoordinator, createStaticShardRegistry, createWorker, decorateResponse, defineRpcEnvelope, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, mergeStrategyForAggregate, otlpSink, pipelineLogSink, resolveLunoraOptions, resolveSecurity, resolveShard, routeIdentityResolvers, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookSink, withFrameworkWorker };
3216
+ export { type AdminTableResolver, type AirbyteMessage, type AnalyticsEngineDataPointLike, type AnalyticsEngineDatasetLike, type AnalyticsEngineSinkOptions, type AuthAdmin, type AuthCapabilities, type AuthConfigInfo, type AuthImpersonation, type AuthPage, type AuthSession, type AuthUser, type AuthUserFieldSpec, type BackupManifest, type BackupStore, type ComposeIdentityResolversErrorMode, type ComposeIdentityResolversOptions, type ConnectorChange, type ConnectorSyncPage, type CorsOptions, type CronHandler, type CronJobDispatch, type CronJobInfo, type CrossShardCounter, type CrossShardReader, type CrossShardRelationCapabilities, type CrossShardRelationOptions, type CsrfOptions, DEFAULT_LOG_COLUMNS, DEFAULT_LOG_LIMIT, DEFAULT_REGISTRY_CACHE_TTL_MS, type DurableObjectJurisdiction, type DynamicShardRegistry, type DynamicShardRegistryOptions, type ExecutionContextLike, type ExportFanOutRequest, type ExportFanOutResult, type FanOutRequest, type FanOutResult, type FanOutSpec, type FivetranResponse, type FrameworkHostHandler, type FrameworkWorkerOptions, type FrameworkWorkerOptionsInput, type FunctionDescriptor, type FunctionRegistryEntry, type FunctionRegistryLike, type GlobalExportFunction as GlobalExportFn, type GlobalImportFunction as GlobalImportFn, type GlobalIntrospector, type GlobalTableInfo as GlobalTableInfoMeta, type GlobalTablePage as GlobalTablePageMeta, type HttpActionContext, type HttpActionLike, type HttpRouterLike, type IdentityContractLike, type IdentityResolver, type IdentityValidation, type ImportFanOutRequest, type ImportFanOutResult, type KvIntrospector, type KvKeyEntry, type KvKeyListResult, type KvNamespaceSummary, type KvValueResult, LOG_ARCHIVE_NOT_CONFIGURED, LOG_ARCHIVE_PATH, type ListAuthUsersOptions, type LogArchiveConfig, type LogEvent, type LogFields, type LogLevel, LunoraError, type LunoraErrorBody, type LunoraHandlerOptions, type LunoraWorker, type MergeStrategy, type MetricEvent, type MetricKind, type MigrationFanOutRequest, type MigrationFanOutResult, NOOP_EXECUTION_CONTEXT, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type OtlpSinkOptions, type PipelineLike, type PipelineLogColumnMap, type PipelineLogCursor, type PipelineLogField, type PipelineLogPage, type PipelineLogQuery, type PipelineLogReader, type PipelineLogReaderOptions, type PipelineLogRow, type PipelineLogSinkOptions, type QueryCoordinator, type QueryCoordinatorOptions, type RankFanOutRequest, type RankFanOutResult, type RankPageFanOutRequest, type RankPageFanOutResult, type ResolvedSecurity, type ResolvedShard, type Route, type RpcContext, type RpcEnvelope, SHARD_REGISTRY_DO_NAME, type ScheduledControllerLike, type SecurityHeadersOptions, type SecurityOptions, type SentrySinkOptions, type ShardError, type ShardExportOutcome, type ShardImportOutcome, type ShardMigrationOutcome, type ShardNamespaceLike, type ShardRankOutcome, type ShardRankPageOutcome, type ShardRegistry, type ShardTrafficEntry, type ShardTrafficFanOutRequest, type ShardTrafficFanOutResult, type ShardingInfo, type SpanEvent, type StorageListFunction as StorageListFn, type StorageObject, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createLunoraHandler, createPipelineLogReader, createQueryCoordinator, createStaticShardRegistry, createWorker, decorateResponse, defineRpcEnvelope, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, mergeStrategyForAggregate, otlpSink, pipelineLogSink, resolveLunoraOptions, resolveSecurity, resolveShard, routeIdentityResolvers, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookSink, withFrameworkWorker };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
+ import { R2SqlClient } from '@lunora/bindings/r2sql';
1
2
  import { RankDirection, RankPageRow, DatabaseWriterLike } from '@lunora/do';
2
3
  export type { RankDirection as RankPageDirection, RankPageRowKey as RankPageKey, RankPageRow, ShardRankPageResult } from '@lunora/do';
3
4
  import { WorkflowsRestClient } from '@lunora/workflow';
4
5
  import { LunoraError as LunoraError$1, ErrorBody } from '@lunora/errors';
5
- import { R2SqlClient } from '@lunora/bindings/r2sql';
6
6
  /**
7
7
  * Turn-key incremental-sync source helpers for warehouse connectors
8
8
  * (Fivetran custom functions, Airbyte incremental sources).
@@ -662,6 +662,172 @@ interface LogEvent {
662
662
  /** Acting userId, or absent when anonymous. */
663
663
  userId?: string;
664
664
  }
665
+ /**
666
+ * The written-column contract: every field `pipelineLogSink` emits, mapped to the
667
+ * column it is stored under by default (the identity mapping). Also the source of
668
+ * truth for the {@link PipelineLogField} union. Mirrors the record built in
669
+ * `pipelineLogSink` — the read side of the same contract.
670
+ */
671
+ declare const DEFAULT_COLUMNS: {
672
+ readonly fields: "fields";
673
+ readonly functionPath: "functionPath";
674
+ readonly level: "level";
675
+ readonly message: "message";
676
+ readonly shardKey: "shardKey";
677
+ readonly spanId: "spanId";
678
+ readonly traceId: "traceId";
679
+ readonly ts: "ts";
680
+ readonly userId: "userId";
681
+ };
682
+ /**
683
+ * The canonical field names of one persisted log record — the keys
684
+ * `pipelineLogSink` writes. Used as the {@link PipelineLogColumnMap} keys and the
685
+ * {@link PipelineLogRow} shape, so the reader stays decoupled from whatever
686
+ * physical column names the operator's Iceberg table happens to use.
687
+ */
688
+ type PipelineLogField = keyof typeof DEFAULT_COLUMNS;
689
+ /**
690
+ * Field-to-column-name map. Defaults to the identity mapping (each field stored
691
+ * under its own name, matching what `pipelineLogSink` writes). Override per-field
692
+ * when the Iceberg schema renames a column; unspecified fields keep their
693
+ * default. This is the single knob that lets one reader serve differently shaped
694
+ * Data Catalog tables.
695
+ */
696
+ type PipelineLogColumnMap = Partial<Record<PipelineLogField, string>>;
697
+ /** An opaque keyset cursor: the `ts` of the row after the last one returned. */
698
+ interface PipelineLogCursor {
699
+ /** Epoch-millis boundary; the next page is every row strictly older than this. */
700
+ ts: number;
701
+ }
702
+ /** Filters for one {@link PipelineLogReader} query. Every value is inlined safely (`lit`/`sql`). */
703
+ interface PipelineLogQuery {
704
+ /** Continue after a previous page (keyset on `ts DESC`). Combined with the other filters. */
705
+ cursor?: PipelineLogCursor;
706
+ /** Match only this exact function path's records. Prefer `functionPathPrefix` for a namespace sweep. */
707
+ functionPath?: string;
708
+ /** Match records whose `functionPath` starts with this string (rendered as a `LIKE 'prefix%'`). */
709
+ functionPathPrefix?: string;
710
+ /** Match only this exact severity. When set, `minLevel` is ignored for the same field. */
711
+ level?: ContextLogLevel;
712
+ /** Max rows to return. Clamped to `[1, 10000]`; defaults to {@link DEFAULT_LOG_LIMIT}. */
713
+ limit?: number;
714
+ /** Severity floor: keep every level at or above this in {@link LOG_LEVEL_ORDER} (e.g. `warn` keeps warn, error, fatal). */
715
+ minLevel?: ContextLogLevel;
716
+ /** Match only this shard key. */
717
+ shardKey?: string;
718
+ /** Lower time bound, inclusive (`ts` at or after this), epoch-millis. */
719
+ sinceTs?: number;
720
+ /** Match only this trace id. */
721
+ traceId?: string;
722
+ /** Upper time bound, inclusive (`ts` at or before this), epoch-millis. */
723
+ untilTs?: number;
724
+ /** Match only this acting user id. */
725
+ userId?: string;
726
+ }
727
+ /**
728
+ * One decoded log record. Always keyed by the canonical {@link PipelineLogField}
729
+ * names regardless of the physical columns (the reader remaps via `columnMap`),
730
+ * so consumers never see the operator's storage names.
731
+ */
732
+ interface PipelineLogRow {
733
+ /**
734
+ * Structured fields, when the record carried them. A `serializeFields` sink
735
+ * stores these as a JSON string, which the reader parses back to an object;
736
+ * a plain string that is not valid JSON is returned verbatim.
737
+ */
738
+ fields?: unknown;
739
+ /** Function path that emitted the line, e.g. `"messages:list"`. */
740
+ functionPath: string;
741
+ /** Severity the line was logged at. */
742
+ level: ContextLogLevel;
743
+ /** Rendered message. */
744
+ message: string;
745
+ /** Shard key for single-shard calls, when present. */
746
+ shardKey?: string;
747
+ /** Span id the line was emitted under, when present. */
748
+ spanId?: string;
749
+ /** Trace id the line belongs to, when present. */
750
+ traceId?: string;
751
+ /** Epoch-millis the line was emitted. */
752
+ ts: number;
753
+ /** Acting user id, when present. */
754
+ userId?: string;
755
+ }
756
+ /** One page of {@link PipelineLogRow}s, newest first, plus the cursor for the next page (absent means last page). */
757
+ interface PipelineLogPage {
758
+ /** The cursor to pass as {@link PipelineLogQuery} `cursor` for the following page; absent when this is the last page. */
759
+ nextCursor?: PipelineLogCursor;
760
+ /** The rows, ordered `ts DESC` (newest first). At most `limit` of them. */
761
+ rows: PipelineLogRow[];
762
+ }
763
+ /** Options for {@link createPipelineLogReader}. */
764
+ interface PipelineLogReaderOptions {
765
+ /**
766
+ * Override any physical column name that diverges from the default (identity)
767
+ * mapping. Unspecified fields keep their {@link DEFAULT_LOG_COLUMNS} name.
768
+ */
769
+ columnMap?: PipelineLogColumnMap;
770
+ /**
771
+ * The Iceberg namespace the `table` lives in (R2 Data Catalog database).
772
+ * Combined as `namespace.table` in the `FROM` clause; omit when `table`
773
+ * already carries its namespace.
774
+ */
775
+ namespace?: string;
776
+ /** The Iceberg table name the Pipeline writes log records to (e.g. `"logs"`). */
777
+ table: string;
778
+ }
779
+ /** The reader surface: a single keyset-paginated {@link PipelineLogPage} query. */
780
+ interface PipelineLogReader {
781
+ /** Run one filtered, keyset-paginated read and return a {@link PipelineLogPage}. */
782
+ query: (query?: PipelineLogQuery) => Promise<PipelineLogPage>;
783
+ }
784
+ /** The written-column contract exposed publicly: canonical field to default physical column name. */
785
+ declare const DEFAULT_LOG_COLUMNS: Readonly<Record<PipelineLogField, string>>;
786
+ /** Default page size when a query omits `limit`. */
787
+ declare const DEFAULT_LOG_LIMIT: number;
788
+ /**
789
+ * Build a durable-log reader over one R2 Data Catalog (Iceberg) table.
790
+ *
791
+ * The returned {@link PipelineLogReader} compiles each call to a safe
792
+ * `SELECT ... WHERE ... ORDER BY ts DESC LIMIT n` (over-fetching by one) and
793
+ * decodes the rows back to the canonical {@link PipelineLogRow} shape. All value
794
+ * filters are escaped through `@lunora/bindings/r2sql`'s `sql`/`lit`; column
795
+ * names come from `options.columnMap` (operator config), spliced with `raw`.
796
+ * @param client An {@link R2SqlClient} (`createR2Sql({ accountId, apiToken, bucket })`).
797
+ * @param options The target `table` (plus optional `namespace`) and any `columnMap` overrides.
798
+ */
799
+ declare const createPipelineLogReader: (client: R2SqlClient, options: PipelineLogReaderOptions) => PipelineLogReader;
800
+ /**
801
+ * Wire constants for the durable log archive, shared between the server route
802
+ * (`@lunora/runtime`'s `log-archive-admin-routes`) and the Studio Archive feed
803
+ * (`@lunora/studio`). Kept here — not in `@lunora/runtime` — because the studio
804
+ * is a browser bundle that must not import a runtime *value* (which would drag
805
+ * the DO/R2-SQL runtime into the browser). This file is dependency-free and
806
+ * bundler-inlined into each consumer, so both sides share one source of truth
807
+ * with no dependency edge.
808
+ */
809
+ /**
810
+ * The error `code` the archive route returns (400) when the operator has wired
811
+ * no archive table (`logArchive`) or the `R2_SQL_*` credentials are missing. The
812
+ * Studio keys its "not configured" empty state off this exact value.
813
+ */
814
+ declare const LOG_ARCHIVE_NOT_CONFIGURED = "LOG_ARCHIVE_NOT_CONFIGURED";
815
+ /** The route the studio's `queryLogArchive` client method POSTs to. */
816
+ declare const LOG_ARCHIVE_PATH = "/_lunora/admin/logs/archive";
817
+ /**
818
+ * The app-level archive config the worker passes through: which Data Catalog
819
+ * table the Pipeline writes log records to (the read-side of `pipelineLogSink`),
820
+ * plus optional namespace / physical-column overrides. The R2 SQL *credentials*
821
+ * are NOT here — they live on `env` (`R2_SQL_*`), read per request.
822
+ */
823
+ interface LogArchiveConfig {
824
+ /** Override any physical column name that diverges from the {@link createPipelineLogReader} default mapping. */
825
+ columnMap?: PipelineLogColumnMap;
826
+ /** The Iceberg namespace (R2 Data Catalog database) the table lives in; omit when `table` already carries it. */
827
+ namespace?: string;
828
+ /** The Iceberg table the Pipeline writes log records to (e.g. `"logs"`). */
829
+ table: string;
830
+ }
665
831
  /**
666
832
  * What kind of instrument produced a measurement, which decides how a collector
667
833
  * aggregates it:
@@ -2275,6 +2441,15 @@ interface WorkerOptions {
2275
2441
  * Omit it and those endpoints respond `KV_NOT_CONFIGURED`.
2276
2442
  */
2277
2443
  kvIntrospector?: KvIntrospector;
2444
+ /**
2445
+ * The durable log archive's read config — the R2 Data Catalog (Iceberg)
2446
+ * table `pipelineLogSink` writes to, so the studio Logs panel's Archive feed
2447
+ * (and the `/_lunora/admin/logs/archive` route) can read it back via R2 SQL.
2448
+ * The R2 SQL credentials come from `env` (`R2_SQL_ACCOUNT_ID` / `R2_SQL_TOKEN`
2449
+ * / `R2_SQL_BUCKET`); this only names the table (+ optional namespace / column
2450
+ * overrides). Absent → the Archive feed reports "not configured".
2451
+ */
2452
+ logArchive?: LogArchiveConfig;
2278
2453
  /**
2279
2454
  * Optional telemetry sink. When supplied, the worker emits one
2280
2455
  * `onRpc` event per dispatched RPC (single-shard forward or fan-out)
@@ -3037,140 +3212,5 @@ declare const otlpSink: (options: OtlpSinkOptions) => ObservabilitySink;
3037
3212
  * @param sinks The sinks to fan out to.
3038
3213
  */
3039
3214
  declare const combineSinks: (...sinks: ObservabilitySink[]) => ObservabilitySink;
3040
- /**
3041
- * The written-column contract: every field `pipelineLogSink` emits, mapped to the
3042
- * column it is stored under by default (the identity mapping). Also the source of
3043
- * truth for the {@link PipelineLogField} union. Mirrors the record built in
3044
- * `pipelineLogSink` — the read side of the same contract.
3045
- */
3046
- declare const DEFAULT_COLUMNS: {
3047
- readonly fields: "fields";
3048
- readonly functionPath: "functionPath";
3049
- readonly level: "level";
3050
- readonly message: "message";
3051
- readonly shardKey: "shardKey";
3052
- readonly spanId: "spanId";
3053
- readonly traceId: "traceId";
3054
- readonly ts: "ts";
3055
- readonly userId: "userId";
3056
- };
3057
- /**
3058
- * The canonical field names of one persisted log record — the keys
3059
- * `pipelineLogSink` writes. Used as the {@link PipelineLogColumnMap} keys and the
3060
- * {@link PipelineLogRow} shape, so the reader stays decoupled from whatever
3061
- * physical column names the operator's Iceberg table happens to use.
3062
- */
3063
- type PipelineLogField = keyof typeof DEFAULT_COLUMNS;
3064
- /**
3065
- * Field-to-column-name map. Defaults to the identity mapping (each field stored
3066
- * under its own name, matching what `pipelineLogSink` writes). Override per-field
3067
- * when the Iceberg schema renames a column; unspecified fields keep their
3068
- * default. This is the single knob that lets one reader serve differently shaped
3069
- * Data Catalog tables.
3070
- */
3071
- type PipelineLogColumnMap = Partial<Record<PipelineLogField, string>>;
3072
- /** An opaque keyset cursor: the `ts` of the row after the last one returned. */
3073
- interface PipelineLogCursor {
3074
- /** Epoch-millis boundary; the next page is every row strictly older than this. */
3075
- ts: number;
3076
- }
3077
- /** Filters for one {@link PipelineLogReader} query. Every value is inlined safely (`lit`/`sql`). */
3078
- interface PipelineLogQuery {
3079
- /** Continue after a previous page (keyset on `ts DESC`). Combined with the other filters. */
3080
- cursor?: PipelineLogCursor;
3081
- /** Match only this exact function path's records. Prefer `functionPathPrefix` for a namespace sweep. */
3082
- functionPath?: string;
3083
- /** Match records whose `functionPath` starts with this string (rendered as a `LIKE 'prefix%'`). */
3084
- functionPathPrefix?: string;
3085
- /** Match only this exact severity. When set, `minLevel` is ignored for the same field. */
3086
- level?: ContextLogLevel;
3087
- /** Max rows to return. Clamped to `[1, 10000]`; defaults to {@link DEFAULT_LOG_LIMIT}. */
3088
- limit?: number;
3089
- /** Severity floor: keep every level at or above this in {@link LOG_LEVEL_ORDER} (e.g. `warn` keeps warn, error, fatal). */
3090
- minLevel?: ContextLogLevel;
3091
- /** Match only this shard key. */
3092
- shardKey?: string;
3093
- /** Lower time bound, inclusive (`ts` at or after this), epoch-millis. */
3094
- sinceTs?: number;
3095
- /** Match only this trace id. */
3096
- traceId?: string;
3097
- /** Upper time bound, inclusive (`ts` at or before this), epoch-millis. */
3098
- untilTs?: number;
3099
- /** Match only this acting user id. */
3100
- userId?: string;
3101
- }
3102
- /**
3103
- * One decoded log record. Always keyed by the canonical {@link PipelineLogField}
3104
- * names regardless of the physical columns (the reader remaps via `columnMap`),
3105
- * so consumers never see the operator's storage names.
3106
- */
3107
- interface PipelineLogRow {
3108
- /**
3109
- * Structured fields, when the record carried them. A `serializeFields` sink
3110
- * stores these as a JSON string, which the reader parses back to an object;
3111
- * a plain string that is not valid JSON is returned verbatim.
3112
- */
3113
- fields?: unknown;
3114
- /** Function path that emitted the line, e.g. `"messages:list"`. */
3115
- functionPath: string;
3116
- /** Severity the line was logged at. */
3117
- level: ContextLogLevel;
3118
- /** Rendered message. */
3119
- message: string;
3120
- /** Shard key for single-shard calls, when present. */
3121
- shardKey?: string;
3122
- /** Span id the line was emitted under, when present. */
3123
- spanId?: string;
3124
- /** Trace id the line belongs to, when present. */
3125
- traceId?: string;
3126
- /** Epoch-millis the line was emitted. */
3127
- ts: number;
3128
- /** Acting user id, when present. */
3129
- userId?: string;
3130
- }
3131
- /** One page of {@link PipelineLogRow}s, newest first, plus the cursor for the next page (absent means last page). */
3132
- interface PipelineLogPage {
3133
- /** The cursor to pass as {@link PipelineLogQuery} `cursor` for the following page; absent when this is the last page. */
3134
- nextCursor?: PipelineLogCursor;
3135
- /** The rows, ordered `ts DESC` (newest first). At most `limit` of them. */
3136
- rows: PipelineLogRow[];
3137
- }
3138
- /** Options for {@link createPipelineLogReader}. */
3139
- interface PipelineLogReaderOptions {
3140
- /**
3141
- * Override any physical column name that diverges from the default (identity)
3142
- * mapping. Unspecified fields keep their {@link DEFAULT_LOG_COLUMNS} name.
3143
- */
3144
- columnMap?: PipelineLogColumnMap;
3145
- /**
3146
- * The Iceberg namespace the `table` lives in (R2 Data Catalog database).
3147
- * Combined as `namespace.table` in the `FROM` clause; omit when `table`
3148
- * already carries its namespace.
3149
- */
3150
- namespace?: string;
3151
- /** The Iceberg table name the Pipeline writes log records to (e.g. `"logs"`). */
3152
- table: string;
3153
- }
3154
- /** The reader surface: a single keyset-paginated {@link PipelineLogPage} query. */
3155
- interface PipelineLogReader {
3156
- /** Run one filtered, keyset-paginated read and return a {@link PipelineLogPage}. */
3157
- query: (query?: PipelineLogQuery) => Promise<PipelineLogPage>;
3158
- }
3159
- /** The written-column contract exposed publicly: canonical field to default physical column name. */
3160
- declare const DEFAULT_LOG_COLUMNS: Readonly<Record<PipelineLogField, string>>;
3161
- /** Default page size when a query omits `limit`. */
3162
- declare const DEFAULT_LOG_LIMIT: number;
3163
- /**
3164
- * Build a durable-log reader over one R2 Data Catalog (Iceberg) table.
3165
- *
3166
- * The returned {@link PipelineLogReader} compiles each call to a safe
3167
- * `SELECT ... WHERE ... ORDER BY ts DESC LIMIT n` (over-fetching by one) and
3168
- * decodes the rows back to the canonical {@link PipelineLogRow} shape. All value
3169
- * filters are escaped through `@lunora/bindings/r2sql`'s `sql`/`lit`; column
3170
- * names come from `options.columnMap` (operator config), spliced with `raw`.
3171
- * @param client An {@link R2SqlClient} (`createR2Sql({ accountId, apiToken, bucket })`).
3172
- * @param options The target `table` (plus optional `namespace`) and any `columnMap` overrides.
3173
- */
3174
- declare const createPipelineLogReader: (client: R2SqlClient, options: PipelineLogReaderOptions) => PipelineLogReader;
3175
3215
  declare const VERSION: string;
3176
- export { type AdminTableResolver, type AirbyteMessage, type AnalyticsEngineDataPointLike, type AnalyticsEngineDatasetLike, type AnalyticsEngineSinkOptions, type AuthAdmin, type AuthCapabilities, type AuthConfigInfo, type AuthImpersonation, type AuthPage, type AuthSession, type AuthUser, type AuthUserFieldSpec, type BackupManifest, type BackupStore, type ComposeIdentityResolversErrorMode, type ComposeIdentityResolversOptions, type ConnectorChange, type ConnectorSyncPage, type CorsOptions, type CronHandler, type CronJobDispatch, type CronJobInfo, type CrossShardCounter, type CrossShardReader, type CrossShardRelationCapabilities, type CrossShardRelationOptions, type CsrfOptions, DEFAULT_LOG_COLUMNS, DEFAULT_LOG_LIMIT, DEFAULT_REGISTRY_CACHE_TTL_MS, type DurableObjectJurisdiction, type DynamicShardRegistry, type DynamicShardRegistryOptions, type ExecutionContextLike, type ExportFanOutRequest, type ExportFanOutResult, type FanOutRequest, type FanOutResult, type FanOutSpec, type FivetranResponse, type FrameworkHostHandler, type FrameworkWorkerOptions, type FrameworkWorkerOptionsInput, type FunctionDescriptor, type FunctionRegistryEntry, type FunctionRegistryLike, type GlobalExportFunction as GlobalExportFn, type GlobalImportFunction as GlobalImportFn, type GlobalIntrospector, type GlobalTableInfo as GlobalTableInfoMeta, type GlobalTablePage as GlobalTablePageMeta, type HttpActionContext, type HttpActionLike, type HttpRouterLike, type IdentityContractLike, type IdentityResolver, type IdentityValidation, type ImportFanOutRequest, type ImportFanOutResult, type KvIntrospector, type KvKeyEntry, type KvKeyListResult, type KvNamespaceSummary, type KvValueResult, type ListAuthUsersOptions, type LogEvent, type LogFields, type LogLevel, LunoraError, type LunoraErrorBody, type LunoraHandlerOptions, type LunoraWorker, type MergeStrategy, type MetricEvent, type MetricKind, type MigrationFanOutRequest, type MigrationFanOutResult, NOOP_EXECUTION_CONTEXT, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type OtlpSinkOptions, type PipelineLike, type PipelineLogColumnMap, type PipelineLogCursor, type PipelineLogField, type PipelineLogPage, type PipelineLogQuery, type PipelineLogReader, type PipelineLogReaderOptions, type PipelineLogRow, type PipelineLogSinkOptions, type QueryCoordinator, type QueryCoordinatorOptions, type RankFanOutRequest, type RankFanOutResult, type RankPageFanOutRequest, type RankPageFanOutResult, type ResolvedSecurity, type ResolvedShard, type Route, type RpcContext, type RpcEnvelope, SHARD_REGISTRY_DO_NAME, type ScheduledControllerLike, type SecurityHeadersOptions, type SecurityOptions, type SentrySinkOptions, type ShardError, type ShardExportOutcome, type ShardImportOutcome, type ShardMigrationOutcome, type ShardNamespaceLike, type ShardRankOutcome, type ShardRankPageOutcome, type ShardRegistry, type ShardTrafficEntry, type ShardTrafficFanOutRequest, type ShardTrafficFanOutResult, type ShardingInfo, type SpanEvent, type StorageListFunction as StorageListFn, type StorageObject, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createLunoraHandler, createPipelineLogReader, createQueryCoordinator, createStaticShardRegistry, createWorker, decorateResponse, defineRpcEnvelope, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, mergeStrategyForAggregate, otlpSink, pipelineLogSink, resolveLunoraOptions, resolveSecurity, resolveShard, routeIdentityResolvers, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookSink, withFrameworkWorker };
3216
+ export { type AdminTableResolver, type AirbyteMessage, type AnalyticsEngineDataPointLike, type AnalyticsEngineDatasetLike, type AnalyticsEngineSinkOptions, type AuthAdmin, type AuthCapabilities, type AuthConfigInfo, type AuthImpersonation, type AuthPage, type AuthSession, type AuthUser, type AuthUserFieldSpec, type BackupManifest, type BackupStore, type ComposeIdentityResolversErrorMode, type ComposeIdentityResolversOptions, type ConnectorChange, type ConnectorSyncPage, type CorsOptions, type CronHandler, type CronJobDispatch, type CronJobInfo, type CrossShardCounter, type CrossShardReader, type CrossShardRelationCapabilities, type CrossShardRelationOptions, type CsrfOptions, DEFAULT_LOG_COLUMNS, DEFAULT_LOG_LIMIT, DEFAULT_REGISTRY_CACHE_TTL_MS, type DurableObjectJurisdiction, type DynamicShardRegistry, type DynamicShardRegistryOptions, type ExecutionContextLike, type ExportFanOutRequest, type ExportFanOutResult, type FanOutRequest, type FanOutResult, type FanOutSpec, type FivetranResponse, type FrameworkHostHandler, type FrameworkWorkerOptions, type FrameworkWorkerOptionsInput, type FunctionDescriptor, type FunctionRegistryEntry, type FunctionRegistryLike, type GlobalExportFunction as GlobalExportFn, type GlobalImportFunction as GlobalImportFn, type GlobalIntrospector, type GlobalTableInfo as GlobalTableInfoMeta, type GlobalTablePage as GlobalTablePageMeta, type HttpActionContext, type HttpActionLike, type HttpRouterLike, type IdentityContractLike, type IdentityResolver, type IdentityValidation, type ImportFanOutRequest, type ImportFanOutResult, type KvIntrospector, type KvKeyEntry, type KvKeyListResult, type KvNamespaceSummary, type KvValueResult, LOG_ARCHIVE_NOT_CONFIGURED, LOG_ARCHIVE_PATH, type ListAuthUsersOptions, type LogArchiveConfig, type LogEvent, type LogFields, type LogLevel, LunoraError, type LunoraErrorBody, type LunoraHandlerOptions, type LunoraWorker, type MergeStrategy, type MetricEvent, type MetricKind, type MigrationFanOutRequest, type MigrationFanOutResult, NOOP_EXECUTION_CONTEXT, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type OtlpSinkOptions, type PipelineLike, type PipelineLogColumnMap, type PipelineLogCursor, type PipelineLogField, type PipelineLogPage, type PipelineLogQuery, type PipelineLogReader, type PipelineLogReaderOptions, type PipelineLogRow, type PipelineLogSinkOptions, type QueryCoordinator, type QueryCoordinatorOptions, type RankFanOutRequest, type RankFanOutResult, type RankPageFanOutRequest, type RankPageFanOutResult, type ResolvedSecurity, type ResolvedShard, type Route, type RpcContext, type RpcEnvelope, SHARD_REGISTRY_DO_NAME, type ScheduledControllerLike, type SecurityHeadersOptions, type SecurityOptions, type SentrySinkOptions, type ShardError, type ShardExportOutcome, type ShardImportOutcome, type ShardMigrationOutcome, type ShardNamespaceLike, type ShardRankOutcome, type ShardRankPageOutcome, type ShardRegistry, type ShardTrafficEntry, type ShardTrafficFanOutRequest, type ShardTrafficFanOutResult, type ShardingInfo, type SpanEvent, type StorageListFunction as StorageListFn, type StorageObject, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createLunoraHandler, createPipelineLogReader, createQueryCoordinator, createStaticShardRegistry, createWorker, decorateResponse, defineRpcEnvelope, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, mergeStrategyForAggregate, otlpSink, pipelineLogSink, resolveLunoraOptions, resolveSecurity, resolveShard, routeIdentityResolvers, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookSink, withFrameworkWorker };
package/dist/index.mjs CHANGED
@@ -1,14 +1,16 @@
1
1
  export { toAirbyteMessages, toFivetranResponse } from './packem_shared/toAirbyteMessages-DrHdplb4.mjs';
2
- export { composeWorker, createLunoraHandler, createWorker, defineRpcEnvelope, resolveLunoraOptions, withFrameworkWorker } from './packem_shared/composeWorker-CqUlK17X.mjs';
2
+ export { composeWorker, createLunoraHandler, createWorker, defineRpcEnvelope, resolveLunoraOptions, withFrameworkWorker } from './packem_shared/composeWorker-DHyRiFho.mjs';
3
3
  export { createCrossShardRelationCapabilities } from './packem_shared/createCrossShardRelationCapabilities-CbcWjkAn.mjs';
4
4
  export { DEFAULT_REGISTRY_CACHE_TTL_MS, SHARD_REGISTRY_DO_NAME, createDynamicShardRegistry } from './packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-B3pA7aXp.mjs';
5
5
  export { LunoraError, toErrorResponse } from './packem_shared/LunoraError-Bpb9EFJ3.mjs';
6
+ export { LOG_ARCHIVE_PATH } from './packem_shared/LOG_ARCHIVE_PATH-iKUShT0P.mjs';
6
7
  export { emitLogEvent, emitRpcEvent } from './packem_shared/emitLogEvent-pEdtqAK8.mjs';
7
8
  export { analyticsEngineSink, combineSinks, consoleSink, otlpSink, pipelineLogSink, sentrySink, webhookSink } from './packem_shared/analyticsEngineSink-Bn7p0URe.mjs';
8
- export { DEFAULT_LOG_COLUMNS, DEFAULT_LOG_LIMIT, createPipelineLogReader } from './packem_shared/DEFAULT_LOG_COLUMNS-J94BHDTf.mjs';
9
+ export { D as DEFAULT_LOG_COLUMNS, a as DEFAULT_LOG_LIMIT, c as createPipelineLogReader } from './packem_shared/pipeline-log-reader-BXULGNC3.mjs';
9
10
  export { createQueryCoordinator, createStaticShardRegistry, mergeStrategyForAggregate } from './packem_shared/createQueryCoordinator-DNCJzOZE.mjs';
10
11
  export { applyJurisdiction, resolveShard } from './packem_shared/applyJurisdiction-BkZtTkct.mjs';
11
12
  export { decorateResponse, enforceOrigin, handleCorsPreflight, resolveSecurity } from './packem_shared/decorateResponse-DRWQFNhF.mjs';
13
+ export { LOG_ARCHIVE_NOT_CONFIGURED } from './packem_shared/LOG_ARCHIVE_NOT_CONFIGURED-acNcguqc.mjs';
12
14
  export { NOOP_EXECUTION_CONTEXT } from './packem_shared/NOOP_EXECUTION_CONTEXT-CCTu0Bf1.mjs';
13
15
  export { composeIdentityResolvers, routeIdentityResolvers } from './packem_shared/composeIdentityResolvers-XGjO7V1J.mjs';
14
16
 
@@ -0,0 +1,2 @@
1
+ import '@lunora/bindings/r2sql';
2
+ export { D as DEFAULT_LOG_COLUMNS, a as DEFAULT_LOG_LIMIT, c as createPipelineLogReader } from './pipeline-log-reader-BXULGNC3.mjs';
@@ -0,0 +1,3 @@
1
+ const LOG_ARCHIVE_NOT_CONFIGURED = "LOG_ARCHIVE_NOT_CONFIGURED";
2
+
3
+ export { LOG_ARCHIVE_NOT_CONFIGURED };
@@ -0,0 +1,111 @@
1
+ import { createR2Sql } from '@lunora/bindings/r2sql';
2
+ import { LOG_ARCHIVE_NOT_CONFIGURED } from './LOG_ARCHIVE_NOT_CONFIGURED-acNcguqc.mjs';
3
+ import { L as LOG_LEVEL_ORDER, c as createPipelineLogReader } from './pipeline-log-reader-BXULGNC3.mjs';
4
+ import { LunoraError } from './LunoraError-Bpb9EFJ3.mjs';
5
+
6
+ const LOG_ARCHIVE_PATH = "/_lunora/admin/logs/archive";
7
+ const LOG_LEVELS = new Set(LOG_LEVEL_ORDER);
8
+ const optionalString = (value) => typeof value === "string" && value !== "" ? value : void 0;
9
+ const parseLevel = (value, field) => {
10
+ if (value === void 0) {
11
+ return void 0;
12
+ }
13
+ if (typeof value !== "string" || !LOG_LEVELS.has(value)) {
14
+ throw new LunoraError(`logs archive: invalid \`${field}\` — expected one of ${LOG_LEVEL_ORDER.join(", ")}`, { code: "BAD_REQUEST", status: 400 });
15
+ }
16
+ return value;
17
+ };
18
+ const parseFiniteNumber = (value, field) => {
19
+ if (value === void 0) {
20
+ return void 0;
21
+ }
22
+ if (typeof value !== "number" || !Number.isFinite(value)) {
23
+ throw new LunoraError(`logs archive: invalid \`${field}\` — expected a finite number`, { code: "BAD_REQUEST", status: 400 });
24
+ }
25
+ return value;
26
+ };
27
+ const parseQuery = (body) => {
28
+ const query = {};
29
+ const assignString = (field) => {
30
+ const value = optionalString(body[field]);
31
+ if (value !== void 0) {
32
+ query[field] = value;
33
+ }
34
+ };
35
+ assignString("functionPath");
36
+ assignString("functionPathPrefix");
37
+ assignString("traceId");
38
+ assignString("shardKey");
39
+ assignString("userId");
40
+ const level = parseLevel(body["level"], "level");
41
+ if (level !== void 0) {
42
+ query.level = level;
43
+ }
44
+ const minLevel = parseLevel(body["minLevel"], "minLevel");
45
+ if (minLevel !== void 0) {
46
+ query.minLevel = minLevel;
47
+ }
48
+ const sinceTs = parseFiniteNumber(body["sinceTs"], "sinceTs");
49
+ if (sinceTs !== void 0) {
50
+ query.sinceTs = sinceTs;
51
+ }
52
+ const untilTs = parseFiniteNumber(body["untilTs"], "untilTs");
53
+ if (untilTs !== void 0) {
54
+ query.untilTs = untilTs;
55
+ }
56
+ const limit = parseFiniteNumber(body["limit"], "limit");
57
+ if (limit !== void 0) {
58
+ query.limit = limit;
59
+ }
60
+ const rawCursor = body["cursor"];
61
+ if (typeof rawCursor === "object" && rawCursor !== null) {
62
+ const cursorTs = parseFiniteNumber(rawCursor["ts"], "cursor.ts");
63
+ if (cursorTs !== void 0) {
64
+ query.cursor = { ts: cursorTs };
65
+ }
66
+ }
67
+ return query;
68
+ };
69
+ const resolveCredentials = (environment) => {
70
+ const accountId = environment.R2_SQL_ACCOUNT_ID ?? environment.CLOUDFLARE_ACCOUNT_ID;
71
+ const apiToken = environment.R2_SQL_TOKEN;
72
+ const bucket = environment.R2_SQL_BUCKET;
73
+ const missing = [];
74
+ if (accountId === void 0 || accountId === "") {
75
+ missing.push("R2_SQL_ACCOUNT_ID");
76
+ }
77
+ if (apiToken === void 0 || apiToken === "") {
78
+ missing.push("R2_SQL_TOKEN");
79
+ }
80
+ if (bucket === void 0 || bucket === "") {
81
+ missing.push("R2_SQL_BUCKET");
82
+ }
83
+ if (missing.length > 0) {
84
+ throw new LunoraError(
85
+ `log archive not configured (missing ${missing.join(", ")}). The Pipeline must write to an R2 Data Catalog (Iceberg) table, and R2_SQL_ACCOUNT_ID / R2_SQL_TOKEN / R2_SQL_BUCKET must be set — see the observability docs.`,
86
+ { code: LOG_ARCHIVE_NOT_CONFIGURED, status: 400 }
87
+ );
88
+ }
89
+ return { accountId, apiToken, bucket };
90
+ };
91
+ const buildLogArchiveAdminRoutes = (deps) => {
92
+ const { createReader = createPipelineLogReader, readJsonBody, requireAdminOption } = deps;
93
+ const handleLogArchive = async (request, env) => {
94
+ if (request.method !== "POST") {
95
+ throw new LunoraError("Log-archive endpoint requires POST", { code: "METHOD_NOT_ALLOWED", status: 405 });
96
+ }
97
+ const config = requireAdminOption(request, deps.logArchive, {
98
+ code: LOG_ARCHIVE_NOT_CONFIGURED,
99
+ message: "log archive requires a `logArchive` config (an R2 Data Catalog table) on the worker — see the observability docs"
100
+ });
101
+ const { accountId, apiToken, bucket } = resolveCredentials(env ?? {});
102
+ const query = parseQuery(await readJsonBody(request));
103
+ const client = createR2Sql({ accountId, apiToken, bucket });
104
+ const reader = createReader(client, { columnMap: config.columnMap, namespace: config.namespace, table: config.table });
105
+ const page = await reader.query(query);
106
+ return Response.json(page, { headers: { "content-type": "application/json" }, status: 200 });
107
+ };
108
+ return { [LOG_ARCHIVE_PATH]: handleLogArchive };
109
+ };
110
+
111
+ export { LOG_ARCHIVE_NOT_CONFIGURED, LOG_ARCHIVE_PATH, buildLogArchiveAdminRoutes };
@@ -4,6 +4,7 @@ import { o as otlpRandomHex, b as buildTraceparent } from './otlp-DOLuy1Aj.mjs';
4
4
  import { LunoraError, toErrorResponse } from './LunoraError-Bpb9EFJ3.mjs';
5
5
  import { wrapResolverWithContract } from './composeIdentityResolvers-XGjO7V1J.mjs';
6
6
  export { composeIdentityResolvers, routeIdentityResolvers } from './composeIdentityResolvers-XGjO7V1J.mjs';
7
+ import { buildLogArchiveAdminRoutes } from './LOG_ARCHIVE_PATH-iKUShT0P.mjs';
7
8
  import { emitRpcEvent } from './emitLogEvent-pEdtqAK8.mjs';
8
9
  import { resolveShard, applyJurisdiction } from './applyJurisdiction-BkZtTkct.mjs';
9
10
  import { resolveSecurity, handleCorsPreflight, enforceOrigin, decorateResponse, enforceWebSocketOrigin } from './decorateResponse-DRWQFNhF.mjs';
@@ -2569,6 +2570,11 @@ const createWorker = (options) => {
2569
2570
  readJsonBody: readJsonBodyWithLimit,
2570
2571
  requireAdminOption
2571
2572
  });
2573
+ const logArchiveAdminRoutes = buildLogArchiveAdminRoutes({
2574
+ logArchive: options.logArchive,
2575
+ readJsonBody: readJsonBodyWithLimit,
2576
+ requireAdminOption
2577
+ });
2572
2578
  const introspectionAdminRoutes = buildIntrospectionAdminRoutes({
2573
2579
  assertAdmin: assertAdminAuthorized,
2574
2580
  options: {
@@ -3208,6 +3214,7 @@ const createWorker = (options) => {
3208
3214
  ...storageAdminRoutes,
3209
3215
  ...vectorAdminRoutes,
3210
3216
  ...kvAdminRoutes,
3217
+ ...logArchiveAdminRoutes,
3211
3218
  ...introspectionAdminRoutes,
3212
3219
  // `/_lunora/admin/auth/*` — the whole user-management plane, one route per
3213
3220
  // `AuthAdmin` op, dispatched by the descriptor table in `./auth-admin-routes`.
@@ -132,4 +132,4 @@ const createPipelineLogReader = (client, options) => {
132
132
  };
133
133
  };
134
134
 
135
- export { DEFAULT_LOG_COLUMNS, DEFAULT_LOG_LIMIT, createPipelineLogReader };
135
+ export { DEFAULT_LOG_COLUMNS as D, LOG_LEVEL_ORDER as L, DEFAULT_LOG_LIMIT as a, createPipelineLogReader as c };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/runtime",
3
- "version": "1.0.0-alpha.31",
3
+ "version": "1.0.0-alpha.32",
4
4
  "description": "Lunora Worker runtime: the RPC router, shard resolver, and query coordinator",
5
5
  "keywords": [
6
6
  "cloudflare",