@lunora/runtime 1.0.0-alpha.36 → 1.0.0-alpha.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/index.d.mts +149 -1
  2. package/dist/index.d.ts +149 -1
  3. package/dist/index.mjs +1 -22
  4. package/dist/packem_shared/DEFAULT_LOG_COLUMNS-CpZ9kd-q.mjs +1 -0
  5. package/dist/packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-BBf3mNrD.mjs +1 -0
  6. package/dist/packem_shared/GET_AUTH_AUDIT_LOG_OP-DmxHQbZT.mjs +1 -0
  7. package/dist/packem_shared/HEALTH_PATH-DiZqjEGp.mjs +1 -0
  8. package/dist/packem_shared/LOG_ARCHIVE_NOT_CONFIGURED-CDpi4yFD.mjs +1 -0
  9. package/dist/packem_shared/LOG_ARCHIVE_PATH-e8U3ftfM.mjs +1 -0
  10. package/dist/packem_shared/LunoraError-C08OP5Uq.mjs +1 -0
  11. package/dist/packem_shared/NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs +1 -0
  12. package/dist/packem_shared/analyticsEngineSink-pVh4v2aY.mjs +1 -0
  13. package/dist/packem_shared/applyJurisdiction-uRQLx282.mjs +1 -0
  14. package/dist/packem_shared/argsFromQuery-0KrWTkNx.mjs +1 -0
  15. package/dist/packem_shared/composeIdentityResolvers-DlBbYmBJ.mjs +1 -0
  16. package/dist/packem_shared/composeWorker-BayjP04B.mjs +6 -0
  17. package/dist/packem_shared/createCrossShardRelationCapabilities-B2EKbSEs.mjs +1 -0
  18. package/dist/packem_shared/createKvCursorStore-C24tEuYk.mjs +3 -0
  19. package/dist/packem_shared/createQueryCoordinator-DLsrcOkB.mjs +1 -0
  20. package/dist/packem_shared/createShardClient-62qcYKGl.mjs +1 -0
  21. package/dist/packem_shared/decorateResponse-C6TZSzID.mjs +1 -0
  22. package/dist/packem_shared/emitLogEvent-COcU_7dj.mjs +1 -0
  23. package/dist/packem_shared/memoizeIdentity-DRYIK1yT.mjs +1 -0
  24. package/dist/packem_shared/method-guard-BbuR0VfS.mjs +1 -0
  25. package/dist/packem_shared/observability-D3GeW_py.mjs +1 -0
  26. package/dist/packem_shared/otlp-resource-Ck1njnSc.mjs +1 -0
  27. package/dist/packem_shared/pipeline-log-reader-tDuvc_Ty.mjs +1 -0
  28. package/dist/packem_shared/toAirbyteMessages-DBTuFjb5.mjs +1 -0
  29. package/package.json +3 -3
  30. package/dist/packem_shared/DEFAULT_LOG_COLUMNS-B7H3YdJ3.mjs +0 -2
  31. package/dist/packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-B3pA7aXp.mjs +0 -79
  32. package/dist/packem_shared/HEALTH_PATH-e5J_NHBx.mjs +0 -150
  33. package/dist/packem_shared/LOG_ARCHIVE_NOT_CONFIGURED-acNcguqc.mjs +0 -3
  34. package/dist/packem_shared/LOG_ARCHIVE_PATH-CNs0bznX.mjs +0 -125
  35. package/dist/packem_shared/LunoraError-Bpb9EFJ3.mjs +0 -22
  36. package/dist/packem_shared/NOOP_EXECUTION_CONTEXT-CCTu0Bf1.mjs +0 -8
  37. package/dist/packem_shared/analyticsEngineSink-yLFNjHDt.mjs +0 -429
  38. package/dist/packem_shared/applyJurisdiction-BkZtTkct.mjs +0 -20
  39. package/dist/packem_shared/argsFromQuery-c-U1WRy-.mjs +0 -121
  40. package/dist/packem_shared/composeIdentityResolvers-XGjO7V1J.mjs +0 -55
  41. package/dist/packem_shared/composeWorker-DiWwOXXt.mjs +0 -3738
  42. package/dist/packem_shared/createCrossShardRelationCapabilities-CbcWjkAn.mjs +0 -63
  43. package/dist/packem_shared/createKvCursorStore-g8aA6B4L.mjs +0 -165
  44. package/dist/packem_shared/createQueryCoordinator-DNCJzOZE.mjs +0 -847
  45. package/dist/packem_shared/decorateResponse-DRWQFNhF.mjs +0 -273
  46. package/dist/packem_shared/emitLogEvent-BlGMnKZK.mjs +0 -1
  47. package/dist/packem_shared/method-guard-Qzw99aCj.mjs +0 -3
  48. package/dist/packem_shared/observability--NOFYBFc.mjs +0 -47
  49. package/dist/packem_shared/otlp-resource-Dow6-F_u.mjs +0 -163
  50. package/dist/packem_shared/pipeline-log-reader-BXULGNC3.mjs +0 -135
  51. package/dist/packem_shared/toAirbyteMessages-DrHdplb4.mjs +0 -39
package/dist/index.d.mts CHANGED
@@ -2187,6 +2187,23 @@ interface CorsOptions {
2187
2187
  }
2188
2188
  /** Origin/CSRF guard configuration. */
2189
2189
  interface CsrfOptions {
2190
+ /**
2191
+ * Whether a loopback `Origin` is trusted **when the worker itself is serving on
2192
+ * loopback**. Defaults to `true`.
2193
+ *
2194
+ * This is the local-development shape: the browser loads the app from the dev
2195
+ * server on `localhost:3000` which proxies `/_lunora` to wrangler on
2196
+ * `localhost:8787`. With `changeOrigin`, the worker sees its own URL as
2197
+ * `:8787` while the browser's `Origin` stays `:3000`, so the two don't match and
2198
+ * the cookie-bearing WS upgrade is rejected — the app then hangs on its loading
2199
+ * state with no clue why. Both ends are loopback, so nothing cross-site can
2200
+ * reach them.
2201
+ *
2202
+ * It cannot loosen production: the exemption requires the worker's OWN origin to
2203
+ * be loopback, which a deployed worker's never is. Set `false` for a hardened
2204
+ * local setup that wants the strict same-origin rule.
2205
+ */
2206
+ allowLoopback?: boolean;
2190
2207
  /** Extra origins (beyond same-origin and the CORS allowlist) accepted on unsafe cookie requests. */
2191
2208
  trustedOrigins?: string[];
2192
2209
  }
@@ -2232,6 +2249,7 @@ interface ResolvedCors {
2232
2249
  maxAge: number;
2233
2250
  }
2234
2251
  interface ResolvedCsrf {
2252
+ allowLoopback: boolean;
2235
2253
  enabled: boolean;
2236
2254
  trustedOrigins: string[];
2237
2255
  }
@@ -3754,6 +3772,53 @@ declare class LunoraError extends LunoraError$1 {
3754
3772
  });
3755
3773
  toResponse(): Response;
3756
3774
  }
3775
+ /**
3776
+ * Memoize a resolver **within a single request**.
3777
+ *
3778
+ * The safe default: keyed on the `Request` object itself, so the result is reused by
3779
+ * every code path handling that request (the RPC dispatch, each fan-out leg, an
3780
+ * admin gate) and discarded the moment the request is collected. It cannot serve a
3781
+ * stale identity, because it never outlives the request that produced it — a revoked
3782
+ * session is re-verified on the very next request.
3783
+ *
3784
+ * ```ts
3785
+ * createWorker({ resolveIdentity: memoizeIdentityPerRequest(myResolver), … });
3786
+ * ```
3787
+ */
3788
+ declare const memoizeIdentityPerRequest: (resolver: IdentityResolver) => IdentityResolver;
3789
+ /** Tuning for {@link memoizeIdentity}. */
3790
+ interface MemoizeIdentityOptions {
3791
+ /**
3792
+ * Cache size before the oldest entry is evicted. Defaults to 500 — an isolate
3793
+ * serves a bounded set of concurrent users, and an unbounded map in a
3794
+ * long-lived isolate is a leak.
3795
+ */
3796
+ maxEntries?: number;
3797
+ /**
3798
+ * How long a verified identity is reused for the same credential, in ms.
3799
+ * Defaults to 5000.
3800
+ *
3801
+ * **This is the revocation delay.** A signed-out or revoked session keeps
3802
+ * resolving for up to this long, so keep it in the seconds — long enough to
3803
+ * collapse a burst (a page load's parallel queries, one query's fan-out across
3804
+ * shards), short enough that a sign-out is effectively immediate. Do not raise it
3805
+ * into the minutes to save verifications.
3806
+ */
3807
+ ttlMs?: number;
3808
+ }
3809
+ /**
3810
+ * Memoize a resolver **across requests**, keyed on the presented credential, for
3811
+ * `ttlMs`.
3812
+ *
3813
+ * Use it when session verification is genuinely expensive (a JWKS fetch, a D1 read)
3814
+ * and a few seconds of revocation delay is acceptable — see
3815
+ * {@link MemoizeIdentityOptions.ttlMs}, which is the whole trade-off. Composes with
3816
+ * (and subsumes) {@link memoizeIdentityPerRequest}: within one request the same entry
3817
+ * is reused regardless of TTL.
3818
+ *
3819
+ * An anonymous request (no cookie, no bearer) is never cached.
3820
+ */
3821
+ declare const memoizeIdentity: (resolver: IdentityResolver, options?: MemoizeIdentityOptions) => IdentityResolver;
3757
3822
  /** A JS attribute value the encoder maps onto an OTLP `AnyValue`. */
3758
3823
  type OtlpAttributeValue = boolean | number | string;
3759
3824
  /**
@@ -4065,5 +4130,88 @@ declare const otlpSink: (options: OtlpSinkOptions) => ObservabilitySink;
4065
4130
  * @param sinks The sinks to fan out to.
4066
4131
  */
4067
4132
  declare const combineSinks: (...sinks: ObservabilitySink[]) => ObservabilitySink;
4133
+ /**
4134
+ * Structural mirror of `@lunora/client`'s `FunctionReference`, re-declared so this
4135
+ * module carries no `runtime → client` (browser SDK) dependency. The phantom
4136
+ * marker's shape matches, so a generated `api.*` / `internal.*` reference infers
4137
+ * its args and return type through {@link ShardClient.call} unchanged.
4138
+ */
4139
+ interface ShardFunctionReference<Args = unknown, Return = unknown> {
4140
+ readonly __lunoraPhantom?: {
4141
+ args: Args;
4142
+ kind: string;
4143
+ returns: Return;
4144
+ };
4145
+ readonly __lunoraRef: string;
4146
+ }
4147
+ /** Args type of a {@link ShardFunctionReference} (`Record&lt;string, unknown>` for an untyped ref). */
4148
+ type ShardCallArgs<F> = F extends ShardFunctionReference<infer A, infer _R> ? A : Record<string, unknown>;
4149
+ /** Return type of a {@link ShardFunctionReference} (`unknown` for an untyped ref). */
4150
+ type ShardCallReturn<F> = F extends ShardFunctionReference<infer _A, infer R> ? R : unknown;
4151
+ /** A verified end-user identity a shard call runs as. */
4152
+ interface ShardCallerIdentity {
4153
+ /**
4154
+ * Full identity claims, forwarded so `ctx.auth.getIdentity()` and any
4155
+ * claim-reading RLS policy see the same object the HTTP path would build. Omit
4156
+ * to forward only `userId`.
4157
+ */
4158
+ claims?: Record<string, unknown>;
4159
+ /** The verified user id — becomes `ctx.auth.userId` on the shard. */
4160
+ userId: string;
4161
+ }
4162
+ /** Options for {@link createShardClient}. */
4163
+ interface ShardClientOptions {
4164
+ /** Run every call as this verified end-user identity. See {@link ShardClient.as}. */
4165
+ as?: ShardCallerIdentity;
4166
+ /** Pin the DO namespace to a data-residency jurisdiction, exactly as the worker does. */
4167
+ jurisdiction?: DurableObjectJurisdiction;
4168
+ /** Default shard key for calls that don't pass one. See {@link ShardClient.forShard}. */
4169
+ shardKey?: string;
4170
+ /**
4171
+ * Whether calls carry system privilege (may invoke `internalQuery` /
4172
+ * `internalMutation` / `internalAction`). Defaults to `true` — a caller holding
4173
+ * the DO binding is already inside the trust boundary. Set `false` to make calls
4174
+ * behave exactly like an end-user RPC, so an accidental `internal.*` call is
4175
+ * rejected by the shard instead of succeeding.
4176
+ */
4177
+ system?: boolean;
4178
+ }
4179
+ /** Per-call overrides. */
4180
+ interface ShardCallOptions {
4181
+ /**
4182
+ * Idempotency key. The DO dedupes on `(identity, mutationId)` and replays the
4183
+ * cached result, so an at-least-once retry (a queue redelivery, a webhook resend)
4184
+ * applies the mutation once. Use a key derived from the upstream event, not a
4185
+ * fresh uuid per attempt.
4186
+ */
4187
+ mutationId?: string;
4188
+ /** Override the client's default shard key for this call. */
4189
+ shardKey?: string;
4190
+ }
4191
+ /** A typed caller bound to a namespace + privilege + (optionally) a shard. */
4192
+ interface ShardClient {
4193
+ /** Derive a client that runs as `identity`. Keeps system privilege unless `system: false` was set. */
4194
+ as: (identity: ShardCallerIdentity) => ShardClient;
4195
+ /** Derive a client with no end-user identity — a pure system caller. */
4196
+ asSystem: () => ShardClient;
4197
+ /**
4198
+ * Call a Lunora function on the shard. Pass a generated reference
4199
+ * (`internal.mcp.listNodes`) for typed args and return; a bare
4200
+ * `"namespace:fn"` string works as the escape hatch and returns `unknown`.
4201
+ *
4202
+ * Throws a {@link LunoraError} carrying the server's `code` when the function
4203
+ * fails — the same error shape the browser client surfaces, so a caller branches
4204
+ * on `FORBIDDEN` / `CONFLICT` / … identically on both sides.
4205
+ */
4206
+ call: <F extends ShardFunctionReference | string>(reference: F, args: F extends string ? Record<string, unknown> : ShardCallArgs<F>, options?: ShardCallOptions) => Promise<ShardCallReturn<F>>;
4207
+ /** Derive a client whose calls default to `shardKey`. */
4208
+ forShard: (shardKey: string) => ShardClient;
4209
+ }
4210
+ /**
4211
+ * Create a typed server-side caller over a `ShardDO` namespace binding.
4212
+ *
4213
+ * See the module docs for the privilege model and the authorization caveat.
4214
+ */
4215
+ declare const createShardClient: (namespace: ShardNamespaceLike, options?: ShardClientOptions) => ShardClient;
4068
4216
  declare const VERSION: string;
4069
- 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 ExportBatch, type ExportChange, type ExportCursorStore, type ExportFanOutRequest, type ExportFanOutResult, type ExportSink, type ExportTapFailure, type ExportTapResult, 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, HEALTH_PATH, HEALTH_READY_PATH, type HealthAuthPosture, type HealthBody, type HealthCheckReport, type HealthProbe, type HealthProbeKind, type HealthProbeResult, type HealthRouteDeps, 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 NotifySubscriptionDevice, type NotifySubscriptionStoreLike, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type OtlpResourceAttributes, 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 RateLimiterLike, type ResolvedSecurity, type ResolvedShard, type RestInvoke, type RestRateLimit, type RestRegistryEntry, type RestRegistryLike, type RestRoute, type RestRouteDeps, type Route, type RpcContext, type RpcEnvelope, type RunExportTapOptions, 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, type TraceSamplingConfig, type TraceTrustSignal, type TrustInboundTraceContext, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, argsFromQuery, buildHealthRoutes, buildRestRoutes, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createKvCursorStore, createLunoraHandler, createMemoryCursorStore, createPipelineLogReader, createQueryCoordinator, createRestRateLimit, createStaticShardRegistry, createWorker, d1Probe, decorateResponse, defineExportSink, defineRpcEnvelope, durableObjectProbe, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, mergeStrategyForAggregate, otlpSink, pipelineLogSink, presenceProbe, r2Sink, readShardKey, resolveLogArchiveFromEnv, resolveLunoraOptions, resolveSecurity, resolveShard, restSurfaceFromRegistry, routeIdentityResolvers, runExportTap, sanitizeChange, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookExportSink, webhookSink, withFrameworkWorker };
4217
+ 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 ExportBatch, type ExportChange, type ExportCursorStore, type ExportFanOutRequest, type ExportFanOutResult, type ExportSink, type ExportTapFailure, type ExportTapResult, 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, HEALTH_PATH, HEALTH_READY_PATH, type HealthAuthPosture, type HealthBody, type HealthCheckReport, type HealthProbe, type HealthProbeKind, type HealthProbeResult, type HealthRouteDeps, 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 MemoizeIdentityOptions, type MergeStrategy, type MetricEvent, type MetricKind, type MigrationFanOutRequest, type MigrationFanOutResult, NOOP_EXECUTION_CONTEXT, type NotifySubscriptionDevice, type NotifySubscriptionStoreLike, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type OtlpResourceAttributes, 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 RateLimiterLike, type ResolvedSecurity, type ResolvedShard, type RestInvoke, type RestRateLimit, type RestRegistryEntry, type RestRegistryLike, type RestRoute, type RestRouteDeps, type Route, type RpcContext, type RpcEnvelope, type RunExportTapOptions, SHARD_REGISTRY_DO_NAME, type ScheduledControllerLike, type SecurityHeadersOptions, type SecurityOptions, type SentrySinkOptions, type ShardCallArgs, type ShardCallOptions, type ShardCallReturn, type ShardCallerIdentity, type ShardClient, type ShardClientOptions, type ShardError, type ShardExportOutcome, type ShardFunctionReference, 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, type TraceSamplingConfig, type TraceTrustSignal, type TrustInboundTraceContext, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, argsFromQuery, buildHealthRoutes, buildRestRoutes, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createKvCursorStore, createLunoraHandler, createMemoryCursorStore, createPipelineLogReader, createQueryCoordinator, createRestRateLimit, createShardClient, createStaticShardRegistry, createWorker, d1Probe, decorateResponse, defineExportSink, defineRpcEnvelope, durableObjectProbe, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, memoizeIdentity, memoizeIdentityPerRequest, mergeStrategyForAggregate, otlpSink, pipelineLogSink, presenceProbe, r2Sink, readShardKey, resolveLogArchiveFromEnv, resolveLunoraOptions, resolveSecurity, resolveShard, restSurfaceFromRegistry, routeIdentityResolvers, runExportTap, sanitizeChange, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookExportSink, webhookSink, withFrameworkWorker };
package/dist/index.d.ts CHANGED
@@ -2187,6 +2187,23 @@ interface CorsOptions {
2187
2187
  }
2188
2188
  /** Origin/CSRF guard configuration. */
2189
2189
  interface CsrfOptions {
2190
+ /**
2191
+ * Whether a loopback `Origin` is trusted **when the worker itself is serving on
2192
+ * loopback**. Defaults to `true`.
2193
+ *
2194
+ * This is the local-development shape: the browser loads the app from the dev
2195
+ * server on `localhost:3000` which proxies `/_lunora` to wrangler on
2196
+ * `localhost:8787`. With `changeOrigin`, the worker sees its own URL as
2197
+ * `:8787` while the browser's `Origin` stays `:3000`, so the two don't match and
2198
+ * the cookie-bearing WS upgrade is rejected — the app then hangs on its loading
2199
+ * state with no clue why. Both ends are loopback, so nothing cross-site can
2200
+ * reach them.
2201
+ *
2202
+ * It cannot loosen production: the exemption requires the worker's OWN origin to
2203
+ * be loopback, which a deployed worker's never is. Set `false` for a hardened
2204
+ * local setup that wants the strict same-origin rule.
2205
+ */
2206
+ allowLoopback?: boolean;
2190
2207
  /** Extra origins (beyond same-origin and the CORS allowlist) accepted on unsafe cookie requests. */
2191
2208
  trustedOrigins?: string[];
2192
2209
  }
@@ -2232,6 +2249,7 @@ interface ResolvedCors {
2232
2249
  maxAge: number;
2233
2250
  }
2234
2251
  interface ResolvedCsrf {
2252
+ allowLoopback: boolean;
2235
2253
  enabled: boolean;
2236
2254
  trustedOrigins: string[];
2237
2255
  }
@@ -3754,6 +3772,53 @@ declare class LunoraError extends LunoraError$1 {
3754
3772
  });
3755
3773
  toResponse(): Response;
3756
3774
  }
3775
+ /**
3776
+ * Memoize a resolver **within a single request**.
3777
+ *
3778
+ * The safe default: keyed on the `Request` object itself, so the result is reused by
3779
+ * every code path handling that request (the RPC dispatch, each fan-out leg, an
3780
+ * admin gate) and discarded the moment the request is collected. It cannot serve a
3781
+ * stale identity, because it never outlives the request that produced it — a revoked
3782
+ * session is re-verified on the very next request.
3783
+ *
3784
+ * ```ts
3785
+ * createWorker({ resolveIdentity: memoizeIdentityPerRequest(myResolver), … });
3786
+ * ```
3787
+ */
3788
+ declare const memoizeIdentityPerRequest: (resolver: IdentityResolver) => IdentityResolver;
3789
+ /** Tuning for {@link memoizeIdentity}. */
3790
+ interface MemoizeIdentityOptions {
3791
+ /**
3792
+ * Cache size before the oldest entry is evicted. Defaults to 500 — an isolate
3793
+ * serves a bounded set of concurrent users, and an unbounded map in a
3794
+ * long-lived isolate is a leak.
3795
+ */
3796
+ maxEntries?: number;
3797
+ /**
3798
+ * How long a verified identity is reused for the same credential, in ms.
3799
+ * Defaults to 5000.
3800
+ *
3801
+ * **This is the revocation delay.** A signed-out or revoked session keeps
3802
+ * resolving for up to this long, so keep it in the seconds — long enough to
3803
+ * collapse a burst (a page load's parallel queries, one query's fan-out across
3804
+ * shards), short enough that a sign-out is effectively immediate. Do not raise it
3805
+ * into the minutes to save verifications.
3806
+ */
3807
+ ttlMs?: number;
3808
+ }
3809
+ /**
3810
+ * Memoize a resolver **across requests**, keyed on the presented credential, for
3811
+ * `ttlMs`.
3812
+ *
3813
+ * Use it when session verification is genuinely expensive (a JWKS fetch, a D1 read)
3814
+ * and a few seconds of revocation delay is acceptable — see
3815
+ * {@link MemoizeIdentityOptions.ttlMs}, which is the whole trade-off. Composes with
3816
+ * (and subsumes) {@link memoizeIdentityPerRequest}: within one request the same entry
3817
+ * is reused regardless of TTL.
3818
+ *
3819
+ * An anonymous request (no cookie, no bearer) is never cached.
3820
+ */
3821
+ declare const memoizeIdentity: (resolver: IdentityResolver, options?: MemoizeIdentityOptions) => IdentityResolver;
3757
3822
  /** A JS attribute value the encoder maps onto an OTLP `AnyValue`. */
3758
3823
  type OtlpAttributeValue = boolean | number | string;
3759
3824
  /**
@@ -4065,5 +4130,88 @@ declare const otlpSink: (options: OtlpSinkOptions) => ObservabilitySink;
4065
4130
  * @param sinks The sinks to fan out to.
4066
4131
  */
4067
4132
  declare const combineSinks: (...sinks: ObservabilitySink[]) => ObservabilitySink;
4133
+ /**
4134
+ * Structural mirror of `@lunora/client`'s `FunctionReference`, re-declared so this
4135
+ * module carries no `runtime → client` (browser SDK) dependency. The phantom
4136
+ * marker's shape matches, so a generated `api.*` / `internal.*` reference infers
4137
+ * its args and return type through {@link ShardClient.call} unchanged.
4138
+ */
4139
+ interface ShardFunctionReference<Args = unknown, Return = unknown> {
4140
+ readonly __lunoraPhantom?: {
4141
+ args: Args;
4142
+ kind: string;
4143
+ returns: Return;
4144
+ };
4145
+ readonly __lunoraRef: string;
4146
+ }
4147
+ /** Args type of a {@link ShardFunctionReference} (`Record&lt;string, unknown>` for an untyped ref). */
4148
+ type ShardCallArgs<F> = F extends ShardFunctionReference<infer A, infer _R> ? A : Record<string, unknown>;
4149
+ /** Return type of a {@link ShardFunctionReference} (`unknown` for an untyped ref). */
4150
+ type ShardCallReturn<F> = F extends ShardFunctionReference<infer _A, infer R> ? R : unknown;
4151
+ /** A verified end-user identity a shard call runs as. */
4152
+ interface ShardCallerIdentity {
4153
+ /**
4154
+ * Full identity claims, forwarded so `ctx.auth.getIdentity()` and any
4155
+ * claim-reading RLS policy see the same object the HTTP path would build. Omit
4156
+ * to forward only `userId`.
4157
+ */
4158
+ claims?: Record<string, unknown>;
4159
+ /** The verified user id — becomes `ctx.auth.userId` on the shard. */
4160
+ userId: string;
4161
+ }
4162
+ /** Options for {@link createShardClient}. */
4163
+ interface ShardClientOptions {
4164
+ /** Run every call as this verified end-user identity. See {@link ShardClient.as}. */
4165
+ as?: ShardCallerIdentity;
4166
+ /** Pin the DO namespace to a data-residency jurisdiction, exactly as the worker does. */
4167
+ jurisdiction?: DurableObjectJurisdiction;
4168
+ /** Default shard key for calls that don't pass one. See {@link ShardClient.forShard}. */
4169
+ shardKey?: string;
4170
+ /**
4171
+ * Whether calls carry system privilege (may invoke `internalQuery` /
4172
+ * `internalMutation` / `internalAction`). Defaults to `true` — a caller holding
4173
+ * the DO binding is already inside the trust boundary. Set `false` to make calls
4174
+ * behave exactly like an end-user RPC, so an accidental `internal.*` call is
4175
+ * rejected by the shard instead of succeeding.
4176
+ */
4177
+ system?: boolean;
4178
+ }
4179
+ /** Per-call overrides. */
4180
+ interface ShardCallOptions {
4181
+ /**
4182
+ * Idempotency key. The DO dedupes on `(identity, mutationId)` and replays the
4183
+ * cached result, so an at-least-once retry (a queue redelivery, a webhook resend)
4184
+ * applies the mutation once. Use a key derived from the upstream event, not a
4185
+ * fresh uuid per attempt.
4186
+ */
4187
+ mutationId?: string;
4188
+ /** Override the client's default shard key for this call. */
4189
+ shardKey?: string;
4190
+ }
4191
+ /** A typed caller bound to a namespace + privilege + (optionally) a shard. */
4192
+ interface ShardClient {
4193
+ /** Derive a client that runs as `identity`. Keeps system privilege unless `system: false` was set. */
4194
+ as: (identity: ShardCallerIdentity) => ShardClient;
4195
+ /** Derive a client with no end-user identity — a pure system caller. */
4196
+ asSystem: () => ShardClient;
4197
+ /**
4198
+ * Call a Lunora function on the shard. Pass a generated reference
4199
+ * (`internal.mcp.listNodes`) for typed args and return; a bare
4200
+ * `"namespace:fn"` string works as the escape hatch and returns `unknown`.
4201
+ *
4202
+ * Throws a {@link LunoraError} carrying the server's `code` when the function
4203
+ * fails — the same error shape the browser client surfaces, so a caller branches
4204
+ * on `FORBIDDEN` / `CONFLICT` / … identically on both sides.
4205
+ */
4206
+ call: <F extends ShardFunctionReference | string>(reference: F, args: F extends string ? Record<string, unknown> : ShardCallArgs<F>, options?: ShardCallOptions) => Promise<ShardCallReturn<F>>;
4207
+ /** Derive a client whose calls default to `shardKey`. */
4208
+ forShard: (shardKey: string) => ShardClient;
4209
+ }
4210
+ /**
4211
+ * Create a typed server-side caller over a `ShardDO` namespace binding.
4212
+ *
4213
+ * See the module docs for the privilege model and the authorization caveat.
4214
+ */
4215
+ declare const createShardClient: (namespace: ShardNamespaceLike, options?: ShardClientOptions) => ShardClient;
4068
4216
  declare const VERSION: string;
4069
- 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 ExportBatch, type ExportChange, type ExportCursorStore, type ExportFanOutRequest, type ExportFanOutResult, type ExportSink, type ExportTapFailure, type ExportTapResult, 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, HEALTH_PATH, HEALTH_READY_PATH, type HealthAuthPosture, type HealthBody, type HealthCheckReport, type HealthProbe, type HealthProbeKind, type HealthProbeResult, type HealthRouteDeps, 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 NotifySubscriptionDevice, type NotifySubscriptionStoreLike, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type OtlpResourceAttributes, 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 RateLimiterLike, type ResolvedSecurity, type ResolvedShard, type RestInvoke, type RestRateLimit, type RestRegistryEntry, type RestRegistryLike, type RestRoute, type RestRouteDeps, type Route, type RpcContext, type RpcEnvelope, type RunExportTapOptions, 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, type TraceSamplingConfig, type TraceTrustSignal, type TrustInboundTraceContext, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, argsFromQuery, buildHealthRoutes, buildRestRoutes, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createKvCursorStore, createLunoraHandler, createMemoryCursorStore, createPipelineLogReader, createQueryCoordinator, createRestRateLimit, createStaticShardRegistry, createWorker, d1Probe, decorateResponse, defineExportSink, defineRpcEnvelope, durableObjectProbe, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, mergeStrategyForAggregate, otlpSink, pipelineLogSink, presenceProbe, r2Sink, readShardKey, resolveLogArchiveFromEnv, resolveLunoraOptions, resolveSecurity, resolveShard, restSurfaceFromRegistry, routeIdentityResolvers, runExportTap, sanitizeChange, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookExportSink, webhookSink, withFrameworkWorker };
4217
+ 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 ExportBatch, type ExportChange, type ExportCursorStore, type ExportFanOutRequest, type ExportFanOutResult, type ExportSink, type ExportTapFailure, type ExportTapResult, 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, HEALTH_PATH, HEALTH_READY_PATH, type HealthAuthPosture, type HealthBody, type HealthCheckReport, type HealthProbe, type HealthProbeKind, type HealthProbeResult, type HealthRouteDeps, 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 MemoizeIdentityOptions, type MergeStrategy, type MetricEvent, type MetricKind, type MigrationFanOutRequest, type MigrationFanOutResult, NOOP_EXECUTION_CONTEXT, type NotifySubscriptionDevice, type NotifySubscriptionStoreLike, type ObservabilityEvent, type ObservabilitySink, type ObservabilitySinkContext, type OtlpResourceAttributes, 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 RateLimiterLike, type ResolvedSecurity, type ResolvedShard, type RestInvoke, type RestRateLimit, type RestRegistryEntry, type RestRegistryLike, type RestRoute, type RestRouteDeps, type Route, type RpcContext, type RpcEnvelope, type RunExportTapOptions, SHARD_REGISTRY_DO_NAME, type ScheduledControllerLike, type SecurityHeadersOptions, type SecurityOptions, type SentrySinkOptions, type ShardCallArgs, type ShardCallOptions, type ShardCallReturn, type ShardCallerIdentity, type ShardClient, type ShardClientOptions, type ShardError, type ShardExportOutcome, type ShardFunctionReference, 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, type TraceSamplingConfig, type TraceTrustSignal, type TrustInboundTraceContext, VERSION, type VectorIndexSummary, type VectorIntrospector, type VectorQueryMatch, type WebhookSinkOptions, type WorkerOptions, analyticsEngineSink, applyJurisdiction, argsFromQuery, buildHealthRoutes, buildRestRoutes, combineSinks, composeIdentityResolvers, composeWorker, consoleSink, createCrossShardRelationCapabilities, createDynamicShardRegistry, createKvCursorStore, createLunoraHandler, createMemoryCursorStore, createPipelineLogReader, createQueryCoordinator, createRestRateLimit, createShardClient, createStaticShardRegistry, createWorker, d1Probe, decorateResponse, defineExportSink, defineRpcEnvelope, durableObjectProbe, emitLogEvent, emitRpcEvent, enforceOrigin, handleCorsPreflight, memoizeIdentity, memoizeIdentityPerRequest, mergeStrategyForAggregate, otlpSink, pipelineLogSink, presenceProbe, r2Sink, readShardKey, resolveLogArchiveFromEnv, resolveLunoraOptions, resolveSecurity, resolveShard, restSurfaceFromRegistry, routeIdentityResolvers, runExportTap, sanitizeChange, sentrySink, toAirbyteMessages, toErrorResponse, toFivetranResponse, webhookExportSink, webhookSink, withFrameworkWorker };
package/dist/index.mjs CHANGED
@@ -1,22 +1 @@
1
- export { toAirbyteMessages, toFivetranResponse } from './packem_shared/toAirbyteMessages-DrHdplb4.mjs';
2
- export { composeWorker, createLunoraHandler, createWorker, defineRpcEnvelope, resolveLunoraOptions, withFrameworkWorker } from './packem_shared/composeWorker-DiWwOXXt.mjs';
3
- export { createCrossShardRelationCapabilities } from './packem_shared/createCrossShardRelationCapabilities-CbcWjkAn.mjs';
4
- export { DEFAULT_REGISTRY_CACHE_TTL_MS, SHARD_REGISTRY_DO_NAME, createDynamicShardRegistry } from './packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-B3pA7aXp.mjs';
5
- export { LunoraError, toErrorResponse } from './packem_shared/LunoraError-Bpb9EFJ3.mjs';
6
- export { createKvCursorStore, createMemoryCursorStore, defineExportSink, r2Sink, runExportTap, sanitizeChange, webhookExportSink } from './packem_shared/createKvCursorStore-g8aA6B4L.mjs';
7
- export { HEALTH_PATH, HEALTH_READY_PATH, buildHealthRoutes, d1Probe, durableObjectProbe, presenceProbe } from './packem_shared/HEALTH_PATH-e5J_NHBx.mjs';
8
- export { LOG_ARCHIVE_PATH, resolveLogArchiveFromEnv } from './packem_shared/LOG_ARCHIVE_PATH-CNs0bznX.mjs';
9
- export { e as emitLogEvent, a as emitRpcEvent } from './packem_shared/observability--NOFYBFc.mjs';
10
- export { analyticsEngineSink, combineSinks, consoleSink, otlpSink, pipelineLogSink, sentrySink, webhookSink } from './packem_shared/analyticsEngineSink-yLFNjHDt.mjs';
11
- export { D as DEFAULT_LOG_COLUMNS, a as DEFAULT_LOG_LIMIT, c as createPipelineLogReader } from './packem_shared/pipeline-log-reader-BXULGNC3.mjs';
12
- export { createQueryCoordinator, createStaticShardRegistry, mergeStrategyForAggregate } from './packem_shared/createQueryCoordinator-DNCJzOZE.mjs';
13
- export { applyJurisdiction, resolveShard } from './packem_shared/applyJurisdiction-BkZtTkct.mjs';
14
- export { argsFromQuery, buildRestRoutes, createRestRateLimit, readShardKey, restSurfaceFromRegistry } from './packem_shared/argsFromQuery-c-U1WRy-.mjs';
15
- export { decorateResponse, enforceOrigin, handleCorsPreflight, resolveSecurity } from './packem_shared/decorateResponse-DRWQFNhF.mjs';
16
- export { LOG_ARCHIVE_NOT_CONFIGURED } from './packem_shared/LOG_ARCHIVE_NOT_CONFIGURED-acNcguqc.mjs';
17
- export { NOOP_EXECUTION_CONTEXT } from './packem_shared/NOOP_EXECUTION_CONTEXT-CCTu0Bf1.mjs';
18
- export { composeIdentityResolvers, routeIdentityResolvers } from './packem_shared/composeIdentityResolvers-XGjO7V1J.mjs';
19
-
20
- const VERSION = "0.0.0";
21
-
22
- export { VERSION };
1
+ import{toAirbyteMessages as t,toFivetranResponse as i}from"./packem_shared/toAirbyteMessages-DBTuFjb5.mjs";import{composeWorker as n,createLunoraHandler as s,createWorker as p,defineRpcEnvelope as m,resolveLunoraOptions as c,withFrameworkWorker as R}from"./packem_shared/composeWorker-BayjP04B.mjs";import{createCrossShardRelationCapabilities as E}from"./packem_shared/createCrossShardRelationCapabilities-B2EKbSEs.mjs";import{DEFAULT_REGISTRY_CACHE_TTL_MS as x,SHARD_REGISTRY_DO_NAME as d,createDynamicShardRegistry as l}from"./packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-BBf3mNrD.mjs";import{LunoraError as L,toErrorResponse as g}from"./packem_shared/LunoraError-C08OP5Uq.mjs";import{createKvCursorStore as y,createMemoryCursorStore as T,defineExportSink as A,r2Sink as k,runExportTap as C,sanitizeChange as O,webhookExportSink as h}from"./packem_shared/createKvCursorStore-C24tEuYk.mjs";import{HEALTH_PATH as H,HEALTH_READY_PATH as I,buildHealthRoutes as b,d1Probe as F,durableObjectProbe as P,presenceProbe as D}from"./packem_shared/HEALTH_PATH-DiZqjEGp.mjs";import{LOG_ARCHIVE_PATH as G,resolveLogArchiveFromEnv as M}from"./packem_shared/LOG_ARCHIVE_PATH-e8U3ftfM.mjs";import{memoizeIdentity as w,memoizeIdentityPerRequest as z}from"./packem_shared/memoizeIdentity-DRYIK1yT.mjs";import{e as W,a as Y}from"./packem_shared/observability-D3GeW_py.mjs";import{analyticsEngineSink as Q,combineSinks as X,consoleSink as j,otlpSink as q,pipelineLogSink as J,sentrySink as B,webhookSink as Z}from"./packem_shared/analyticsEngineSink-pVh4v2aY.mjs";import{D as ee,a as re,c as oe}from"./packem_shared/pipeline-log-reader-tDuvc_Ty.mjs";import{createQueryCoordinator as ie,createStaticShardRegistry as ae,mergeStrategyForAggregate as ne}from"./packem_shared/createQueryCoordinator-DLsrcOkB.mjs";import{applyJurisdiction as pe,resolveShard as me}from"./packem_shared/applyJurisdiction-uRQLx282.mjs";import{argsFromQuery as Re,buildRestRoutes as Se,createRestRateLimit as Ee,readShardKey as fe,restSurfaceFromRegistry as xe}from"./packem_shared/argsFromQuery-0KrWTkNx.mjs";import{decorateResponse as le,enforceOrigin as _e,handleCorsPreflight as Le,resolveSecurity as ge}from"./packem_shared/decorateResponse-C6TZSzID.mjs";import{createShardClient as ye}from"./packem_shared/createShardClient-62qcYKGl.mjs";import{LOG_ARCHIVE_NOT_CONFIGURED as Ae}from"./packem_shared/LOG_ARCHIVE_NOT_CONFIGURED-CDpi4yFD.mjs";import{NOOP_EXECUTION_CONTEXT as Ce}from"./packem_shared/NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs";import{composeIdentityResolvers as he,routeIdentityResolvers as ve}from"./packem_shared/composeIdentityResolvers-DlBbYmBJ.mjs";const e="0.0.0";export{ee as DEFAULT_LOG_COLUMNS,re as DEFAULT_LOG_LIMIT,x as DEFAULT_REGISTRY_CACHE_TTL_MS,H as HEALTH_PATH,I as HEALTH_READY_PATH,Ae as LOG_ARCHIVE_NOT_CONFIGURED,G as LOG_ARCHIVE_PATH,L as LunoraError,Ce as NOOP_EXECUTION_CONTEXT,d as SHARD_REGISTRY_DO_NAME,e as VERSION,Q as analyticsEngineSink,pe as applyJurisdiction,Re as argsFromQuery,b as buildHealthRoutes,Se as buildRestRoutes,X as combineSinks,he as composeIdentityResolvers,n as composeWorker,j as consoleSink,E as createCrossShardRelationCapabilities,l as createDynamicShardRegistry,y as createKvCursorStore,s as createLunoraHandler,T as createMemoryCursorStore,oe as createPipelineLogReader,ie as createQueryCoordinator,Ee as createRestRateLimit,ye as createShardClient,ae as createStaticShardRegistry,p as createWorker,F as d1Probe,le as decorateResponse,A as defineExportSink,m as defineRpcEnvelope,P as durableObjectProbe,W as emitLogEvent,Y as emitRpcEvent,_e as enforceOrigin,Le as handleCorsPreflight,w as memoizeIdentity,z as memoizeIdentityPerRequest,ne as mergeStrategyForAggregate,q as otlpSink,J as pipelineLogSink,D as presenceProbe,k as r2Sink,fe as readShardKey,M as resolveLogArchiveFromEnv,c as resolveLunoraOptions,ge as resolveSecurity,me as resolveShard,xe as restSurfaceFromRegistry,ve as routeIdentityResolvers,C as runExportTap,O as sanitizeChange,B as sentrySink,t as toAirbyteMessages,g as toErrorResponse,i as toFivetranResponse,h as webhookExportSink,Z as webhookSink,R as withFrameworkWorker};
@@ -0,0 +1 @@
1
+ import"@lunora/bindings/r2sql";import{D as r,a as o,c as _}from"./pipeline-log-reader-tDuvc_Ty.mjs";export{r as DEFAULT_LOG_COLUMNS,o as DEFAULT_LOG_LIMIT,_ as createPipelineLogReader};
@@ -0,0 +1 @@
1
+ import{LunoraError as n}from"./LunoraError-C08OP5Uq.mjs";import{applyJurisdiction as m}from"./applyJurisdiction-uRQLx282.mjs";const S="__lunora_shard_registry__",_=3e4,l="https://shard-registry.internal",w=async s=>await s.json(),$=s=>{const p=s.instanceName??S,o=s.cacheTtlMs??_,a=new Map,c=m(s.namespace,s.jurisdiction);let d;const h=()=>(d??=c.get(c.idFromName(p)),d),y=async(t,e)=>h().fetch(new Request(`${l}${t}`,{body:JSON.stringify(e),headers:{"content-type":"application/json"},method:"POST"})),u=async t=>h().fetch(new Request(`${l}${t}`,{method:"GET"}));return{invalidate(t){t===void 0?a.clear():a.delete(t)},async listShardKeys(t){const e=Date.now(),r=a.get(t);if(r&&r.expiresAt>e)return r.shardKeys;const i=await u(`/list?table=${encodeURIComponent(t)}`);if(!i.ok)throw new n(`shard registry /list returned ${String(i.status)}`);const{shardKeys:g}=await w(i);return o>0&&a.set(t,{expiresAt:e+o,shardKeys:g}),g},async register(t,e){const r=await y("/register",{shardKey:e,table:t});if(!r.ok)throw new n(`shard registry /register returned ${String(r.status)}`);a.delete(t)},async snapshot(){const t=await u("/snapshot");if(!t.ok)throw new n(`shard registry /snapshot returned ${String(t.status)}`);const{tables:e}=await w(t);return e},async unregister(t,e){const r=await y("/unregister",{shardKey:e,table:t});if(!r.ok)throw new n(`shard registry /unregister returned ${String(r.status)}`);a.delete(t)}}};export{_ as DEFAULT_REGISTRY_CACHE_TTL_MS,S as SHARD_REGISTRY_DO_NAME,$ as createDynamicShardRegistry};
@@ -0,0 +1 @@
1
+ import{LunoraError as a}from"./LunoraError-C08OP5Uq.mjs";const p="__lunora_admin__:getAuthAuditLog",A=e=>typeof e=="string"&&e!==""?e:void 0,_=e=>typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0,v=e=>async(h,o)=>{e.assertAdmin(h);const r=e.getReader();if(r===void 0)throw new a("the auth/security audit endpoint requires an `authAuditReader` on the worker",{code:"AUTH_AUDIT_NOT_CONFIGURED",status:400});const t={},n=A(o.actorId),s=A(o.event),d=_(o.sinceSeq),u=_(o.limit);n!==void 0&&(t.actorId=n),s!==void 0&&(t.event=s),d!==void 0&&(t.sinceSeq=d),u!==void 0&&(t.limit=u);let c;try{c=await r.read(t)}catch(i){throw i instanceof a?i:(console.error("[lunora] auth audit read failed:",i),new a("auth audit read failed",{code:"AUTH_AUDIT_READ_FAILED",status:500}))}const l={entries:c};return Response.json(l,{headers:{"content-type":"application/json"},status:200})};export{p as GET_AUTH_AUDIT_LOG_OP,v as buildGetAuthAuditLog};
@@ -0,0 +1 @@
1
+ import{LunoraError as w}from"./LunoraError-C08OP5Uq.mjs";import{d as E}from"./method-guard-BbuR0VfS.mjs";const v="/_lunora/health",A="/_lunora/health/ready",D=a=>a==="liveness"?["liveness"]:a==="readiness"?["readiness"]:["liveness","readiness"];class H{#e=new Map;addChecker(e,r,t){this.#e.set(e,{run:r,types:t.type})}async getReport(e){const r=[...this.#e].filter(([,s])=>e===void 0||s.types.includes(e)),t=await Promise.all(r.map(async([s,i])=>[s,await i.run()]));return{healthy:t.every(([,s])=>s.health.healthy),report:Object.fromEntries(t)}}}const k=a=>{const e=new H,r=new Set;for(const t of a)t.critical&&r.add(t.name),e.addChecker(t.name,async()=>{let s;try{s=await t.check()}catch(i){s={healthy:!1,message:i instanceof Error?i.message:"probe failed"}}return{health:{healthy:s.healthy,...s.message===void 0?{}:{message:s.message}}}},{type:D(t.kind)});return{criticalNames:r,registry:e}},N=(a,e,r,t,s)=>{const i=[];let c=!1,l=!1;for(const[o,h]of Object.entries(a)){const d=e.has(o),u=h.health.healthy;u||(l=!0,d&&(c=!0)),i.push({critical:d,...r==="admin"&&h.health.message!==void 0?{message:h.health.message}:{},name:o,status:u?"up":"down"})}i.sort((o,h)=>o.name.localeCompare(h.name));let n="healthy";return c?n="unhealthy":l&&(n="degraded"),{anyCriticalDown:c,body:{appName:t,appVersion:s,checks:i,status:n,timestamp:new Date().toISOString()}}},P=a=>{const{appName:e="lunora",appVersion:r="0.0.0",auth:t="public",isAdmin:s,resolveProbes:i}=a,c=n=>{if(t==="admin"&&!s(n))throw new w("health endpoint requires a valid admin bearer",{code:"ADMIN_FORBIDDEN",status:403})},l=async(n,o,h)=>{const d=E(n,["GET","HEAD"]);if(d)return d;c(n);const{criticalNames:u,registry:m}=k(i(o)),{healthy:y,report:p}=await m.getReport(h==="readiness"?"readiness":void 0),{anyCriticalDown:f,body:g}=N(p,u,t,e,r),b=h==="readiness"?!y:f;return Response.json(g,{headers:{"cache-control":"no-store"},status:b?503:200})};return{[v]:(n,o)=>l(n,o,"aggregate"),[A]:(n,o)=>l(n,o,"readiness")}},T=(a,e,r)=>({check:async()=>{try{return await e.get(e.idFromName(r)).fetch(new Request("https://shard.internal/_lunora/status",{method:"GET"})),{healthy:!0}}catch{return{healthy:!1,message:"durable object unreachable"}}},critical:!0,name:a}),_=(a,e)=>({check:async()=>{try{return await e.prepare("SELECT 1").first(),{healthy:!0}}catch{return{healthy:!1,message:"d1 query failed"}}},critical:!0,name:a}),j=(a,e)=>({check:()=>e?{healthy:!0}:{healthy:!1,message:"binding not configured"},critical:!1,name:a});export{v as HEALTH_PATH,A as HEALTH_READY_PATH,P as buildHealthRoutes,_ as d1Probe,T as durableObjectProbe,j as presenceProbe};
@@ -0,0 +1 @@
1
+ const O="LOG_ARCHIVE_NOT_CONFIGURED";export{O as LOG_ARCHIVE_NOT_CONFIGURED};
@@ -0,0 +1 @@
1
+ import{createR2Sql as h}from"@lunora/bindings/r2sql";import{LOG_ARCHIVE_NOT_CONFIGURED as p}from"./LOG_ARCHIVE_NOT_CONFIGURED-CDpi4yFD.mjs";import{L as m,c as f}from"./pipeline-log-reader-tDuvc_Ty.mjs";import{LunoraError as _}from"./LunoraError-C08OP5Uq.mjs";const E="/_lunora/admin/logs/archive",A="LUNORA_LOG_ARCHIVE_TABLE",O="LUNORA_LOG_ARCHIVE_NAMESPACE",D=e=>{if(typeof e!="object"||e===null)return;const t=e,o=t[A];if(typeof o!="string"||o==="")return;const i=t[O];return{table:o,...typeof i=="string"&&i!==""?{namespace:i}:{}}},g=new Set(m),b=e=>typeof e=="string"&&e!==""?e:void 0,v=(e,t)=>{if(e!==void 0){if(typeof e!="string"||!g.has(e))throw new _(`logs archive: invalid \`${t}\` — expected one of ${m.join(", ")}`,{code:"BAD_REQUEST",status:400});return e}},d=(e,t)=>{if(e!==void 0){if(typeof e!="number"||!Number.isFinite(e))throw new _(`logs archive: invalid \`${t}\` — expected a finite number`,{code:"BAD_REQUEST",status:400});return e}},C=e=>{const t={},o=r=>{const l=b(e[r]);l!==void 0&&(t[r]=l)};o("functionPath"),o("functionPathPrefix"),o("traceId"),o("shardKey"),o("userId");const i=v(e.level,"level");i!==void 0&&(t.level=i);const n=v(e.minLevel,"minLevel");n!==void 0&&(t.minLevel=n);const s=d(e.sinceTs,"sinceTs");s!==void 0&&(t.sinceTs=s);const u=d(e.untilTs,"untilTs");u!==void 0&&(t.untilTs=u);const a=d(e.limit,"limit");a!==void 0&&(t.limit=a);const c=e.cursor;if(typeof c=="object"&&c!==null){const r=d(c.ts,"cursor.ts");r!==void 0&&(t.cursor={ts:r})}return t},S=e=>{const t=e.R2_SQL_ACCOUNT_ID??e.CLOUDFLARE_ACCOUNT_ID,o=e.R2_SQL_TOKEN,i=e.R2_SQL_BUCKET,n=[];if((t===void 0||t==="")&&n.push("R2_SQL_ACCOUNT_ID"),(o===void 0||o==="")&&n.push("R2_SQL_TOKEN"),(i===void 0||i==="")&&n.push("R2_SQL_BUCKET"),n.length>0)throw new _(`log archive not configured (missing ${n.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.`,{code:p,status:400});return{accountId:t,apiToken:o,bucket:i}},U=e=>{const{createReader:t=f,readJsonBody:o,requireAdminOption:i}=e,n=async(s,u)=>{if(s.method!=="POST")throw new _("Log-archive endpoint requires POST",{code:"METHOD_NOT_ALLOWED",status:405});const a=i(s,e.logArchive,{code:p,message:"log archive requires a `logArchive` config (an R2 Data Catalog table) on the worker — see the observability docs"}),{accountId:c,apiToken:r,bucket:l}=S(u??{}),L=C(await o(s)),T=h({accountId:c,apiToken:r,bucket:l}),R=await t(T,{columnMap:a.columnMap,namespace:a.namespace,table:a.table}).query(L);return Response.json(R,{headers:{"content-type":"application/json"},status:200})};return{[E]:n}};export{p as LOG_ARCHIVE_NOT_CONFIGURED,E as LOG_ARCHIVE_PATH,U as buildLogArchiveAdminRoutes,D as resolveLogArchiveFromEnv};
@@ -0,0 +1 @@
1
+ import{toErrorBody as t,LunoraError as n}from"@lunora/errors";const a=e=>{const{body:o,redacted:r,status:s}=t(e,{fallbackCode:"INTERNAL",redactedMessage:"Internal error"});return r&&console.error("[lunora] internal error:",e),Response.json({error:o},{headers:{"content-type":"application/json"},status:s})};class u extends n{constructor(o,r){super(r?.code??"INTERNAL",o,{cause:r?.cause,status:r?.status})}toResponse(){return a(this)}}export{u as LunoraError,a as toErrorResponse};
@@ -0,0 +1 @@
1
+ const t={passThroughOnException:()=>{},waitUntil:()=>{}};export{t as NOOP_EXECUTION_CONTEXT};
@@ -0,0 +1 @@
1
+ import{a as w,f as T,b as h,c as s,L as I,w as $,e as L,V as N,R}from"./otlp-resource-Ck1njnSc.mjs";const M=e=>{if(typeof e=="string")return e;try{return JSON.stringify(e)??String(e)}catch{return String(e)}},_=e=>typeof e=="boolean"||typeof e=="number"||typeof e=="string"?e:M(e),E=(e,a,t,n)=>{const o=[s("lunora.function_path",e.functionPath),s("lunora.ok",e.ok)];e.method!==void 0&&o.push(s("http.request.method",e.method)),e.path!==void 0&&o.push(s("url.path",e.path)),o.push(s("http.route",e.functionPath)),e.scheme!==void 0&&o.push(s("url.scheme",e.scheme)),e.host!==void 0&&o.push(s("server.address",e.host)),e.port!==void 0&&o.push(s("server.port",e.port)),e.userAgent!==void 0&&o.push(s("user_agent.original",e.userAgent)),e.shardKey!==void 0&&o.push(s("lunora.shard_key",e.shardKey)),o.push(s("http.response.status_code",e.error?.status??200)),e.error&&o.push(s("error.type",e.error.code),s("lunora.error_status",e.error.status)),e.fanOut&&o.push(s("lunora.fanout.table",e.fanOut.table),s("lunora.fanout.shards",e.fanOut.shards),s("lunora.fanout.failed",e.fanOut.failed));const r={attributes:o,endTimeUnixNano:h(t),kind:2,name:e.functionPath,spanId:e.spanId??T(8),startTimeUnixNano:h(t-e.durationMs),status:e.ok?{code:1}:{code:2,message:e.error?.message??""},traceId:e.traceId??T(16)};return e.parentSpanId!==void 0&&(r.parentSpanId=e.parentSpanId),e.traceFlags!==void 0&&(r.flags=e.traceFlags),e.error&&(r.events=[{attributes:[s("exception.type",e.error.code),s("exception.message",e.error.message)],name:"exception",timeUnixNano:h(t)}]),w(r,"@lunora/runtime",a,n)},k=(e,a)=>{const t=new Map([["lunora.function_path",s("lunora.function_path",e.functionPath)]]);e.shardKey!==void 0&&t.set("lunora.shard_key",s("lunora.shard_key",e.shardKey)),e.userId!==void 0&&t.set("lunora.user_id",s("lunora.user_id",e.userId)),e.errorType!==void 0&&t.set("error.type",s("error.type",e.errorType));for(const[n,o]of Object.entries(a??{}))t.set(n,s(n,_(o)));return[...t.values()]},A=(e,a,t)=>{const n={attributes:k({errorType:e.error?.type,functionPath:e.functionPath,shardKey:e.shardKey,userId:e.userId},e.attributes),endTimeUnixNano:h(e.startTs+e.durationMs),kind:1,name:e.name,parentSpanId:e.parentSpanId,spanId:e.spanId,startTimeUnixNano:h(e.startTs),status:e.ok?{code:1}:{code:2,message:e.error?.message??""},traceId:e.traceId};return w(n,"@lunora/runtime",a,t)},F=(e,a,t)=>{const n=h(e.ts),o=k({functionPath:e.functionPath,shardKey:e.shardKey},e.attributes),r={asDouble:e.value,attributes:o,timeUnixNano:n};return e.kind==="gauge"?I({gauge:{dataPoints:[r]},name:e.name},"@lunora/runtime",a,t):e.kind==="histogram"?I({histogram:{aggregationTemporality:1,dataPoints:[{attributes:o,bucketCounts:["1"],count:"1",explicitBounds:[],max:e.value,min:e.value,sum:e.value,timeUnixNano:n}]},name:e.name},"@lunora/runtime",a,t):I({name:e.name,sum:{aggregationTemporality:1,dataPoints:[r],isMonotonic:!0}},"@lunora/runtime",a,t)},V=(e,a,t)=>{const n={attributes:k({functionPath:e.functionPath,shardKey:e.shardKey,userId:e.userId},e.fields),body:{stringValue:e.message},severityNumber:L[e.level],severityText:e.level.toUpperCase(),timeUnixNano:h(e.ts)};return e.traceId!==void 0&&(n.traceId=e.traceId),e.spanId!==void 0&&(n.spanId=e.spanId),$(n,"@lunora/runtime",a,t)},J=1024,j=async e=>{const a=new Blob([e]).stream().pipeThrough(new CompressionStream("gzip"));return new Response(a).arrayBuffer()},b=(e,a,t,n)=>{try{const o=JSON.stringify(a),r=(o.length<J?fetch(e,{body:o,headers:t,method:"POST"}):j(o).then(l=>fetch(e,{body:l,headers:{...t,"content-encoding":"gzip"},method:"POST"}))).catch(()=>{});n?.waitUntil&&n.waitUntil(r)}catch{}},y=(e,a)=>a===!0&&e.ok,B=(e={})=>{const{onlyErrors:a}=e;return{onLog:t=>{t.level==="error"||t.level==="fatal"?console.error("[lunora:log]",t.functionPath,t.message):console.log("[lunora:log]",t.functionPath,t.message)},onMetric:t=>{console.log("[lunora:metric]",`${t.name}=${String(t.value)}`,t.kind,t.functionPath)},onRpc:t=>{y(t,a)||(t.ok?console.log("[lunora:rpc]",t):console.error("[lunora:rpc]",t))},onSpan:t=>{const n=t.ok?"ok":`error ${t.error?.type??""}`.trim();console.log("[lunora:span]",t.name,`${String(t.durationMs)}ms`,n,t.functionPath)}}},C=e=>{const{headers:a,onlyErrors:t,transform:n,transformLog:o,url:r}=e,l=N({"content-type":"application/json"},a),m=(d,p)=>{try{const i=fetch(r,{body:JSON.stringify(d),headers:l,method:"POST"}).catch(()=>{});p?.waitUntil&&p.waitUntil(i)}catch{}};return{onLog:(d,p)=>{let i=d;if(o)try{i=o(d)}catch{return}i!=null&&m(i,p)},onRpc:(d,p)=>{if(!y(d,t))try{let i=d;if(n)try{i=n(d)}catch{return}if(i==null)return;m(i,p)}catch{}}}},D=e=>{const{capture:a,captureLog:t}=e,n=e.onlyErrors??!0;return{onLog:t?o=>{try{t(o)}catch{}}:void 0,onRpc:o=>{if(!y(o,n))try{a(o)}catch{}}}},W=e=>{const{dataset:a,onlyErrors:t}=e;return{onRpc:n=>{if(!y(n,t))try{a.writeDataPoint({blobs:[n.functionPath,n.ok?"ok":"error",n.shardKey??"",n.error?.code??"",n.fanOut?.table??""],doubles:[n.durationMs,n.ok?0:1,n.fanOut?.shards??0,n.fanOut?.failed??0],indexes:[n.functionPath]})}catch{}}}},q=e=>{const{pipeline:a,serializeFields:t}=e;return{onLog:(n,o)=>{try{const r={functionPath:n.functionPath,level:n.level,message:n.message,ts:n.ts};n.fields&&(r.fields=t===!0?JSON.stringify(n.fields):n.fields),n.shardKey!==void 0&&(r.shardKey=n.shardKey),n.userId!==void 0&&(r.userId=n.userId),n.traceId!==void 0&&(r.traceId=n.traceId),n.spanId!==void 0&&(r.spanId=n.spanId);const l=a.send([r]).catch(()=>{});o?.waitUntil&&o.waitUntil(l)}catch{}}}},G=e=>{const{deploymentEnvironment:a,detectResources:t,endpoint:n,headers:o,onlyErrors:r,resourceAttributes:l,serviceNamespace:m,serviceVersion:d,token:p}=e,i=e.serviceName??"lunora",S={...d===void 0?{}:{"service.version":d},...m===void 0?{}:{"service.namespace":m},...a===void 0?{}:{"deployment.environment":a},...l},P=new WeakMap,g=c=>{if(t!==!0||c?.resourceAttributes===void 0)return S;const u=P.get(c);if(u!==void 0)return u;const x=R(c.resourceAttributes(),S);return P.set(c,x),x};let f=n;for(;f.endsWith("/");)f=f.slice(0,-1);const O=`${f}/v1/traces`,U=`${f}/v1/logs`,K=`${f}/v1/metrics`,v=N({"content-type":"application/json"},o,p);return{onLog:(c,u)=>{b(U,V(c,i,g(u)),v,u)},onMetric:(c,u)=>{b(K,F(c,i,g(u)),v,u)},onRpc:(c,u)=>{y(c,r)||b(O,E(c,i,Date.now(),g(u)),v,u)},onSpan:(c,u)=>{b(O,A(c,i,g(u)),v,u)}}},H=(...e)=>{const a=(t,n,o)=>{for(const r of e){const l=r[t];if(l)try{l.call(r,n,o)}catch{}}};return{onLog:(t,n)=>{a("onLog",t,n)},onMetric:(t,n)=>{a("onMetric",t,n)},onRpc:(t,n)=>{a("onRpc",t,n)},onSpan:(t,n)=>{a("onSpan",t,n)}}};export{W as analyticsEngineSink,H as combineSinks,B as consoleSink,G as otlpSink,q as pipelineLogSink,D as sentrySink,C as webhookSink};
@@ -0,0 +1 @@
1
+ const e=(t,o)=>{if(o===void 0)return t;if(typeof t.jurisdiction!="function")throw new TypeError(`@lunora/runtime: Durable Object namespace does not support jurisdiction("${o}") — update @cloudflare/workers-types or remove the jurisdiction option`);return t.jurisdiction(o)},i=(t,o)=>{if(typeof t.getByName=="function")return t.getByName(o);const r=t.idFromName(o);return t.get(r)};export{e as applyJurisdiction,i as resolveShard};
@@ -0,0 +1 @@
1
+ import{d as k}from"./method-guard-BbuR0VfS.mjs";const P="/_lunora/rest",l=n=>{const t=n.indexOf(":");if(!(t<=0||t>=n.length-1||n.indexOf(":",t+1)!==-1))return{name:n.slice(t+1),namespace:n.slice(0,t)}},g=n=>{const t=l(n);if(t!==void 0)return`${P}/${t.namespace}/${t.name}`},v=n=>n==="query"?"GET":"POST",x=n=>{const t=[];for(const e of n){if(e.exposure?.rest!==!0||e.kind==="stream")continue;const r=l(e.functionPath),o=g(e.functionPath);r===void 0||o===void 0||t.push({functionPath:e.functionPath,kind:e.kind,method:v(e.kind),name:r.name,namespace:r.namespace,path:o})}return t.sort((e,r)=>e.path.localeCompare(r.path)),t},R=n=>Object.entries(n).map(([t,e])=>({exposure:e.expose,functionPath:t,kind:e.kind})),T=n=>x(R(n)),w=(n,t)=>{const e=n.searchParams.get("shardKey");if(e!==null&&e!=="")return e;const r=t.headers.get("x-lunora-shard-key");return r===null||r===""?void 0:r},O=n=>{const t={};for(const[e,r]of n.searchParams.entries())if(e!=="shardKey")try{t[e]=JSON.parse(r)}catch{t[e]=r}return t},L=n=>{const{functions:t,invoke:e,rateLimit:r,readJsonBody:o}=n,s={};for(const i of T(t)){const p=i.kind==="query"?["GET","POST"]:["POST"];s[i.path]=async(a,y,S,d)=>{const f=k(a,p);if(f)return f;const h=new URL(a.url);if(r){const c=await r(a,i.functionPath);if(c)return c}let u;a.method==="GET"?u=O(h):u=a.body===null?{}:await o(a);const m=w(h,a);return e({args:u,env:y,functionPath:i.functionPath,request:a,...m===void 0?{}:{shardKey:m},...d?.waitUntil===void 0?{}:{waitUntil:c=>d.waitUntil?.(c)}})}}return s},K=(n,t)=>async(e,r)=>{const o=t.key?t.key(e,r):e.headers.get("cf-connecting-ip")??void 0,s=await n.limit(t.name,o===void 0?{}:{key:o});if(s.ok)return;const i=Math.max(1,Math.ceil(s.retryAfter/1e3));return Response.json({error:{code:"RATE_LIMITED",message:"Rate limit exceeded"}},{headers:{"content-type":"application/json","retry-after":String(i)},status:429})};export{O as argsFromQuery,L as buildRestRoutes,K as createRestRateLimit,w as readShardKey,T as restSurfaceFromRegistry};
@@ -0,0 +1 @@
1
+ import{LunoraError as c}from"./LunoraError-C08OP5Uq.mjs";const u=(r,n={})=>{const t=n.onError??"fail-closed";return async(o,e)=>{for(const i of r){let s;try{s=await i(o,e)}catch(a){if(t==="skip")continue;throw a}if(s)return s}return null}},d=r=>{const n=Object.keys(r).filter(t=>t!=="*").toSorted((t,o)=>o.length-t.length);return(t,o)=>{const{pathname:e}=new URL(t.url),i=n.find(a=>e===a||e.startsWith(a.endsWith("/")?a:`${a}/`)),s=i===void 0?r["*"]:r[i];return s===void 0?null:s(t,o)}},f=(r,n)=>n===void 0||r===void 0?r:async(t,o)=>{const e=await r(t,o);if(!e)return e;const i=n.validate(e);if(i.ok)return e;if(n.onInvalid==="reject")throw new c(`identity claims failed the declared contract: ${i.error}`,{code:"UNAUTHENTICATED",status:401});return null};export{u as composeIdentityResolvers,d as routeIdentityResolvers,f as wrapResolverWithContract};