@lunora/advisor 1.0.0-alpha.88 → 1.0.0-alpha.89

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
@@ -344,6 +344,35 @@ interface AdvisorFailOpenGuard {
344
344
  /** 1-based line of the middleware call, or `0` when unknown. */
345
345
  line: number;
346
346
  }
347
+ /**
348
+ * One `ctx.flags` read discovered lexically inside a `query(...)` handler body —
349
+ * the input the `flag_read_in_subscription` lint consumes. Produced by the
350
+ * codegen feeder, which walks each exported query's handler with ts-morph and
351
+ * records reads of the flag-evaluation surface (`ctx.flags.boolean(...)`,
352
+ * `ctx.flags.string(...)`, `ctx.flags.details.number(...)`, …).
353
+ *
354
+ * A flag read is a point-in-time evaluation, and nothing about it is *wrong* —
355
+ * but the invalidation system does not model it. Flipping a flag appends nothing
356
+ * to `__cdc_log`, so no live subscription is re-run: a query that branched on a
357
+ * flag keeps serving the branch it picked when it last ran, for as long as the
358
+ * client stays subscribed. The reactive path is `useFlag`, which is served
359
+ * through the flags function prefix and re-evaluated on every write-flush.
360
+ *
361
+ * `mutation(...)` and `action(...)` handlers are intentionally **not** recorded —
362
+ * neither backs a live subscription, so a flag read there is evaluated once for a
363
+ * call that also happens once, and there is no staleness to warn about. Runtime
364
+ * callers don't supply this, so the lint finds nothing there.
365
+ */
366
+ interface AdvisorFlagRead {
367
+ /** The accessed `ctx.flags` surface, e.g. `ctx.flags.boolean` / `ctx.flags.details.string`. */
368
+ callee: string;
369
+ /** The exported query performing the read (e.g. `listMessages`). */
370
+ exportName: string;
371
+ /** Source file the read appears in (relative to the lunora dir, no extension). */
372
+ file: string;
373
+ /** 1-based line of the read, or `0` when unknown. */
374
+ line: number;
375
+ }
347
376
  /**
348
377
  * One `ctx.flags.boolean("key", <boolean-literal>)` read — the
349
378
  * `flag_gates_security_with_unsafe_default` lint input. OpenFeature returns the
@@ -1902,6 +1931,16 @@ interface LintContext {
1902
1931
  * the lint finds nothing.
1903
1932
  */
1904
1933
  failOpenGuards?: ReadonlyArray<AdvisorFailOpenGuard>;
1934
+ /**
1935
+ * `ctx.flags` reads lexically inside a `query(...)` handler — the
1936
+ * `flag_read_in_subscription` input. A flag flip appends nothing to `__cdc_log`,
1937
+ * so no live subscription is re-run and the query keeps serving the branch it
1938
+ * last picked; `useFlag` is the reactive path. Only `query` handlers are
1939
+ * recorded — a `mutation`/`action` runs once, so there is no staleness there.
1940
+ * Supplied by the codegen feeder; absent for runtime callers, where the lint
1941
+ * finds nothing.
1942
+ */
1943
+ flagReads?: ReadonlyArray<AdvisorFlagRead>;
1905
1944
  /**
1906
1945
  * `ctx.flags.boolean(key, default)` reads with a statically-known string key and
1907
1946
  * boolean-literal default — the `flag_gates_security_with_unsafe_default` input.
@@ -3058,6 +3097,48 @@ declare const filterWithoutIndex: Lint;
3058
3097
  * low. One finding per read.
3059
3098
  */
3060
3099
  declare const flagGatesSecurityWithUnsafeDefault: Lint;
3100
+ /**
3101
+ * Flags a `ctx.flags` read inside a `query(...)` handler body.
3102
+ *
3103
+ * A flag read is an input the invalidation system does not model. Live queries
3104
+ * re-run off the change feed: a write appends to `__cdc_log`, the shard flushes,
3105
+ * and every subscription whose read set overlaps the write is re-evaluated.
3106
+ * Flipping a feature flag appends nothing — the flag lives in the OpenFeature
3107
+ * provider, not in a Lunora table — so a subscription that branched on
3108
+ * `ctx.flags.boolean("new-ui", false)` keeps serving the branch it picked when it
3109
+ * last ran, for as long as the client stays connected. No error, no reconnect, no
3110
+ * signal of any kind.
3111
+ *
3112
+ * Forcing a re-snapshot on flag change was considered and rejected: it would
3113
+ * converge only the reconnect moment (a permanent cost paid on every reconnect)
3114
+ * while leaving the query stale for exactly the window that matters — a live
3115
+ * client that never disconnects. The reactive path already exists and is correct:
3116
+ * a `useFlag` subscription is served through the flags function prefix, tagged
3117
+ * with the admin wildcard, and re-evaluated on every write-flush. So the answer
3118
+ * for a flag read inside a cached query is to tell the author, exactly as this
3119
+ * repo already does for `Date.now()` in a query.
3120
+ *
3121
+ * WARN rather than INFO — the same axis the sibling
3122
+ * `nondeterministic_query_mutation` splits on. Its mutation half dropped to INFO
3123
+ * because the hazard genuinely is not there: a mutation handler runs at most once
3124
+ * per logical write, so there is nothing for it to be inconsistent with. Here the
3125
+ * hazard *is* there and its failure mode is silence — a stale flag branch looks
3126
+ * exactly like a correct one from the client, so nothing surfaces it at runtime,
3127
+ * and INFO (which most surfaces filter out) would leave the author with no signal
3128
+ * at all. This lint is also structurally low-volume in a way the mutation half
3129
+ * was not: it fires only on queries, and only on an explicit `ctx.flags` touch,
3130
+ * so it cannot flood a real codebase the way "stamp `createdAt` in a mutation"
3131
+ * did (193 of 385 non-INFO findings on one real app).
3132
+ *
3133
+ * `mutation(...)` and `action(...)` are not flagged — the feeder never records
3134
+ * them. Neither backs a live subscription, so a flag read there is a
3135
+ * point-in-time evaluation for a call that is itself point-in-time.
3136
+ *
3137
+ * This lint runs when the codegen feeder has supplied read evidence
3138
+ * (`context.flagReads` present); a runtime caller with no evidence flags nothing
3139
+ * rather than raising false alarms.
3140
+ */
3141
+ declare const flagReadInSubscription: Lint;
3061
3142
  /**
3062
3143
  * A correctness lint exploiting Lunora's static edge: a `.geoIndex(name, { field })`
3063
3144
  * maintains a geohash companion over a `v.geoPoint()` column, and
@@ -4574,4 +4655,4 @@ interface RunAdvisorOptions {
4574
4655
  * `static` lints at build time and defer `runtime` lints to a live shard.
4575
4656
  */
4576
4657
  declare const runAdvisor: (context: LintContext, options?: RunAdvisorOptions) => Finding[];
4577
- export { ALL_LINTS, type AdvisorAdminRoute, type AdvisorAiRawRun, type AdvisorAiToolSideEffect, type AdvisorArgumentDerivedFetch, type AdvisorArgumentValidator, type AdvisorAuthApiCall, type AdvisorAuthConfig, type AdvisorBrowserUrlAccess, type AdvisorConfigCall, type AdvisorContainer, type AdvisorContainerKeyAccess, type AdvisorContainerOverride, type AdvisorExportSink, type AdvisorFailOpenGuard, type AdvisorFlagSecurityDefault, type AdvisorFunctionMetrics, type AdvisorGeoIndexUsage, type AdvisorHttpActionGuard, type AdvisorHttpHeaderWrite, type AdvisorHyperdriveCall, type AdvisorIdentityClaimRead, type AdvisorImageDeliveryUrlAccess, type AdvisorIndex, type AdvisorIndexHit, type AdvisorInsertWrite, type AdvisorKvKeyAccess, type AdvisorMailRecipientAccess, type AdvisorMap, type AdvisorMaskProcedure, type AdvisorMaskStrategy, type AdvisorMutatorWrite, type AdvisorNondeterministicCall, type AdvisorNormalizeIdAuthorization, type AdvisorNotifyCall, type AdvisorNotifyConfig, type AdvisorOwnerFieldWrite, type AdvisorPaymentWebhook, type AdvisorPrivilegedDispatch, type AdvisorProcedureProtection, type AdvisorQueryRead, type AdvisorQueue, type AdvisorQueueTuning, type AdvisorR2sqlCall, type AdvisorRatelimitKeySelector, type AdvisorRawRowReturn, type AdvisorRelation, type AdvisorRelationLoad, type AdvisorRlsProcedure, type AdvisorSchema, type AdvisorSecretLiteral, type AdvisorShape, type AdvisorShardTraffic, type AdvisorSoftDeleteRead, type AdvisorSqlInterpolation, type AdvisorStaleMigrationImport, type AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableSample, type AdvisorTableScan, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type BaselineComparison, type Category, type CheckResult, type Coverage, type Facing, type Finding, type Grade, type Level, type Lint, type LintContext, type LintSource, MAP_VERSION, type MapSummary, type ProcedureDelta, type ProcedureScore, type ProjectScore, RUNTIME_LINTS, RunAdvisorOptions, STATIC_LINTS, type ScoreAdvisorOptions, type Sensitivity, type SensitivityLevel, actionFetchSsrf, actionWithoutErrorHandling, adminRouteWithoutGuard, aiRawRunEscapeHatch, aiRunWithoutLogging, aiToolSideEffectPromptInjection, aiUnboundedGenerationPublic, allowUnauthenticatedShardAccessEnabled, authApiCallWithoutHeaders, authCsrfCheckDisabled, authEmailVerificationDisabled, authScimWithoutTransactions, authSecureCookiesDisabled, authSessionFreshageZero, authTrustedOriginsWildcard, browserAllowPrivateTargets, browserUserUrlWithoutAllowlist, byCodepoint, circularFk, classifySensitivity, commitOrderedHardDelete, compareToBaseline, constraintValidator, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, dedupeCacheKeys, duplicateIndex, emptyIndex, errorRateOutlier, errorWithoutCatalog, exportSinkMisconfigured, externalSourceIncrementalNoDeletePath, externalSourceOnGlobal, externalSourceUnscoped, fanOutBreadth, filterOnPrimaryKey, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, fromServerSchema, geoIndexFieldNotGeopoint, geoIndexUnused, globalTableNearColumnLimit, gradeFromScore, hardcodedSecret, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, kvUnscopedUserKeyIdor, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, notifyMissingPushConfig, notifySendOutsideAction, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, parseAdvisorMap, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, procedureWithoutStructuredEvent, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, scoreAdvisor, shapeTargetsGlobalTable, shapeUnknownTable, signupMutationWithoutDisposableGating, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, ttlFieldNotTimestamp, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, unrestrictedWhereBranch, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
4658
+ export { ALL_LINTS, type AdvisorAdminRoute, type AdvisorAiRawRun, type AdvisorAiToolSideEffect, type AdvisorArgumentDerivedFetch, type AdvisorArgumentValidator, type AdvisorAuthApiCall, type AdvisorAuthConfig, type AdvisorBrowserUrlAccess, type AdvisorConfigCall, type AdvisorContainer, type AdvisorContainerKeyAccess, type AdvisorContainerOverride, type AdvisorExportSink, type AdvisorFailOpenGuard, type AdvisorFlagRead, type AdvisorFlagSecurityDefault, type AdvisorFunctionMetrics, type AdvisorGeoIndexUsage, type AdvisorHttpActionGuard, type AdvisorHttpHeaderWrite, type AdvisorHyperdriveCall, type AdvisorIdentityClaimRead, type AdvisorImageDeliveryUrlAccess, type AdvisorIndex, type AdvisorIndexHit, type AdvisorInsertWrite, type AdvisorKvKeyAccess, type AdvisorMailRecipientAccess, type AdvisorMap, type AdvisorMaskProcedure, type AdvisorMaskStrategy, type AdvisorMutatorWrite, type AdvisorNondeterministicCall, type AdvisorNormalizeIdAuthorization, type AdvisorNotifyCall, type AdvisorNotifyConfig, type AdvisorOwnerFieldWrite, type AdvisorPaymentWebhook, type AdvisorPrivilegedDispatch, type AdvisorProcedureProtection, type AdvisorQueryRead, type AdvisorQueue, type AdvisorQueueTuning, type AdvisorR2sqlCall, type AdvisorRatelimitKeySelector, type AdvisorRawRowReturn, type AdvisorRelation, type AdvisorRelationLoad, type AdvisorRlsProcedure, type AdvisorSchema, type AdvisorSecretLiteral, type AdvisorShape, type AdvisorShardTraffic, type AdvisorSoftDeleteRead, type AdvisorSqlInterpolation, type AdvisorStaleMigrationImport, type AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableSample, type AdvisorTableScan, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type BaselineComparison, type Category, type CheckResult, type Coverage, type Facing, type Finding, type Grade, type Level, type Lint, type LintContext, type LintSource, MAP_VERSION, type MapSummary, type ProcedureDelta, type ProcedureScore, type ProjectScore, RUNTIME_LINTS, RunAdvisorOptions, STATIC_LINTS, type ScoreAdvisorOptions, type Sensitivity, type SensitivityLevel, actionFetchSsrf, actionWithoutErrorHandling, adminRouteWithoutGuard, aiRawRunEscapeHatch, aiRunWithoutLogging, aiToolSideEffectPromptInjection, aiUnboundedGenerationPublic, allowUnauthenticatedShardAccessEnabled, authApiCallWithoutHeaders, authCsrfCheckDisabled, authEmailVerificationDisabled, authScimWithoutTransactions, authSecureCookiesDisabled, authSessionFreshageZero, authTrustedOriginsWildcard, browserAllowPrivateTargets, browserUserUrlWithoutAllowlist, byCodepoint, circularFk, classifySensitivity, commitOrderedHardDelete, compareToBaseline, constraintValidator, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, dedupeCacheKeys, duplicateIndex, emptyIndex, errorRateOutlier, errorWithoutCatalog, exportSinkMisconfigured, externalSourceIncrementalNoDeletePath, externalSourceOnGlobal, externalSourceUnscoped, fanOutBreadth, filterOnPrimaryKey, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, flagReadInSubscription, fromServerSchema, geoIndexFieldNotGeopoint, geoIndexUnused, globalTableNearColumnLimit, gradeFromScore, hardcodedSecret, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, kvUnscopedUserKeyIdor, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, notifyMissingPushConfig, notifySendOutsideAction, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, parseAdvisorMap, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, procedureWithoutStructuredEvent, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, scoreAdvisor, shapeTargetsGlobalTable, shapeUnknownTable, signupMutationWithoutDisposableGating, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, ttlFieldNotTimestamp, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, unrestrictedWhereBranch, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
package/dist/index.d.ts CHANGED
@@ -344,6 +344,35 @@ interface AdvisorFailOpenGuard {
344
344
  /** 1-based line of the middleware call, or `0` when unknown. */
345
345
  line: number;
346
346
  }
347
+ /**
348
+ * One `ctx.flags` read discovered lexically inside a `query(...)` handler body —
349
+ * the input the `flag_read_in_subscription` lint consumes. Produced by the
350
+ * codegen feeder, which walks each exported query's handler with ts-morph and
351
+ * records reads of the flag-evaluation surface (`ctx.flags.boolean(...)`,
352
+ * `ctx.flags.string(...)`, `ctx.flags.details.number(...)`, …).
353
+ *
354
+ * A flag read is a point-in-time evaluation, and nothing about it is *wrong* —
355
+ * but the invalidation system does not model it. Flipping a flag appends nothing
356
+ * to `__cdc_log`, so no live subscription is re-run: a query that branched on a
357
+ * flag keeps serving the branch it picked when it last ran, for as long as the
358
+ * client stays subscribed. The reactive path is `useFlag`, which is served
359
+ * through the flags function prefix and re-evaluated on every write-flush.
360
+ *
361
+ * `mutation(...)` and `action(...)` handlers are intentionally **not** recorded —
362
+ * neither backs a live subscription, so a flag read there is evaluated once for a
363
+ * call that also happens once, and there is no staleness to warn about. Runtime
364
+ * callers don't supply this, so the lint finds nothing there.
365
+ */
366
+ interface AdvisorFlagRead {
367
+ /** The accessed `ctx.flags` surface, e.g. `ctx.flags.boolean` / `ctx.flags.details.string`. */
368
+ callee: string;
369
+ /** The exported query performing the read (e.g. `listMessages`). */
370
+ exportName: string;
371
+ /** Source file the read appears in (relative to the lunora dir, no extension). */
372
+ file: string;
373
+ /** 1-based line of the read, or `0` when unknown. */
374
+ line: number;
375
+ }
347
376
  /**
348
377
  * One `ctx.flags.boolean("key", <boolean-literal>)` read — the
349
378
  * `flag_gates_security_with_unsafe_default` lint input. OpenFeature returns the
@@ -1902,6 +1931,16 @@ interface LintContext {
1902
1931
  * the lint finds nothing.
1903
1932
  */
1904
1933
  failOpenGuards?: ReadonlyArray<AdvisorFailOpenGuard>;
1934
+ /**
1935
+ * `ctx.flags` reads lexically inside a `query(...)` handler — the
1936
+ * `flag_read_in_subscription` input. A flag flip appends nothing to `__cdc_log`,
1937
+ * so no live subscription is re-run and the query keeps serving the branch it
1938
+ * last picked; `useFlag` is the reactive path. Only `query` handlers are
1939
+ * recorded — a `mutation`/`action` runs once, so there is no staleness there.
1940
+ * Supplied by the codegen feeder; absent for runtime callers, where the lint
1941
+ * finds nothing.
1942
+ */
1943
+ flagReads?: ReadonlyArray<AdvisorFlagRead>;
1905
1944
  /**
1906
1945
  * `ctx.flags.boolean(key, default)` reads with a statically-known string key and
1907
1946
  * boolean-literal default — the `flag_gates_security_with_unsafe_default` input.
@@ -3058,6 +3097,48 @@ declare const filterWithoutIndex: Lint;
3058
3097
  * low. One finding per read.
3059
3098
  */
3060
3099
  declare const flagGatesSecurityWithUnsafeDefault: Lint;
3100
+ /**
3101
+ * Flags a `ctx.flags` read inside a `query(...)` handler body.
3102
+ *
3103
+ * A flag read is an input the invalidation system does not model. Live queries
3104
+ * re-run off the change feed: a write appends to `__cdc_log`, the shard flushes,
3105
+ * and every subscription whose read set overlaps the write is re-evaluated.
3106
+ * Flipping a feature flag appends nothing — the flag lives in the OpenFeature
3107
+ * provider, not in a Lunora table — so a subscription that branched on
3108
+ * `ctx.flags.boolean("new-ui", false)` keeps serving the branch it picked when it
3109
+ * last ran, for as long as the client stays connected. No error, no reconnect, no
3110
+ * signal of any kind.
3111
+ *
3112
+ * Forcing a re-snapshot on flag change was considered and rejected: it would
3113
+ * converge only the reconnect moment (a permanent cost paid on every reconnect)
3114
+ * while leaving the query stale for exactly the window that matters — a live
3115
+ * client that never disconnects. The reactive path already exists and is correct:
3116
+ * a `useFlag` subscription is served through the flags function prefix, tagged
3117
+ * with the admin wildcard, and re-evaluated on every write-flush. So the answer
3118
+ * for a flag read inside a cached query is to tell the author, exactly as this
3119
+ * repo already does for `Date.now()` in a query.
3120
+ *
3121
+ * WARN rather than INFO — the same axis the sibling
3122
+ * `nondeterministic_query_mutation` splits on. Its mutation half dropped to INFO
3123
+ * because the hazard genuinely is not there: a mutation handler runs at most once
3124
+ * per logical write, so there is nothing for it to be inconsistent with. Here the
3125
+ * hazard *is* there and its failure mode is silence — a stale flag branch looks
3126
+ * exactly like a correct one from the client, so nothing surfaces it at runtime,
3127
+ * and INFO (which most surfaces filter out) would leave the author with no signal
3128
+ * at all. This lint is also structurally low-volume in a way the mutation half
3129
+ * was not: it fires only on queries, and only on an explicit `ctx.flags` touch,
3130
+ * so it cannot flood a real codebase the way "stamp `createdAt` in a mutation"
3131
+ * did (193 of 385 non-INFO findings on one real app).
3132
+ *
3133
+ * `mutation(...)` and `action(...)` are not flagged — the feeder never records
3134
+ * them. Neither backs a live subscription, so a flag read there is a
3135
+ * point-in-time evaluation for a call that is itself point-in-time.
3136
+ *
3137
+ * This lint runs when the codegen feeder has supplied read evidence
3138
+ * (`context.flagReads` present); a runtime caller with no evidence flags nothing
3139
+ * rather than raising false alarms.
3140
+ */
3141
+ declare const flagReadInSubscription: Lint;
3061
3142
  /**
3062
3143
  * A correctness lint exploiting Lunora's static edge: a `.geoIndex(name, { field })`
3063
3144
  * maintains a geohash companion over a `v.geoPoint()` column, and
@@ -4574,4 +4655,4 @@ interface RunAdvisorOptions {
4574
4655
  * `static` lints at build time and defer `runtime` lints to a live shard.
4575
4656
  */
4576
4657
  declare const runAdvisor: (context: LintContext, options?: RunAdvisorOptions) => Finding[];
4577
- export { ALL_LINTS, type AdvisorAdminRoute, type AdvisorAiRawRun, type AdvisorAiToolSideEffect, type AdvisorArgumentDerivedFetch, type AdvisorArgumentValidator, type AdvisorAuthApiCall, type AdvisorAuthConfig, type AdvisorBrowserUrlAccess, type AdvisorConfigCall, type AdvisorContainer, type AdvisorContainerKeyAccess, type AdvisorContainerOverride, type AdvisorExportSink, type AdvisorFailOpenGuard, type AdvisorFlagSecurityDefault, type AdvisorFunctionMetrics, type AdvisorGeoIndexUsage, type AdvisorHttpActionGuard, type AdvisorHttpHeaderWrite, type AdvisorHyperdriveCall, type AdvisorIdentityClaimRead, type AdvisorImageDeliveryUrlAccess, type AdvisorIndex, type AdvisorIndexHit, type AdvisorInsertWrite, type AdvisorKvKeyAccess, type AdvisorMailRecipientAccess, type AdvisorMap, type AdvisorMaskProcedure, type AdvisorMaskStrategy, type AdvisorMutatorWrite, type AdvisorNondeterministicCall, type AdvisorNormalizeIdAuthorization, type AdvisorNotifyCall, type AdvisorNotifyConfig, type AdvisorOwnerFieldWrite, type AdvisorPaymentWebhook, type AdvisorPrivilegedDispatch, type AdvisorProcedureProtection, type AdvisorQueryRead, type AdvisorQueue, type AdvisorQueueTuning, type AdvisorR2sqlCall, type AdvisorRatelimitKeySelector, type AdvisorRawRowReturn, type AdvisorRelation, type AdvisorRelationLoad, type AdvisorRlsProcedure, type AdvisorSchema, type AdvisorSecretLiteral, type AdvisorShape, type AdvisorShardTraffic, type AdvisorSoftDeleteRead, type AdvisorSqlInterpolation, type AdvisorStaleMigrationImport, type AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableSample, type AdvisorTableScan, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type BaselineComparison, type Category, type CheckResult, type Coverage, type Facing, type Finding, type Grade, type Level, type Lint, type LintContext, type LintSource, MAP_VERSION, type MapSummary, type ProcedureDelta, type ProcedureScore, type ProjectScore, RUNTIME_LINTS, RunAdvisorOptions, STATIC_LINTS, type ScoreAdvisorOptions, type Sensitivity, type SensitivityLevel, actionFetchSsrf, actionWithoutErrorHandling, adminRouteWithoutGuard, aiRawRunEscapeHatch, aiRunWithoutLogging, aiToolSideEffectPromptInjection, aiUnboundedGenerationPublic, allowUnauthenticatedShardAccessEnabled, authApiCallWithoutHeaders, authCsrfCheckDisabled, authEmailVerificationDisabled, authScimWithoutTransactions, authSecureCookiesDisabled, authSessionFreshageZero, authTrustedOriginsWildcard, browserAllowPrivateTargets, browserUserUrlWithoutAllowlist, byCodepoint, circularFk, classifySensitivity, commitOrderedHardDelete, compareToBaseline, constraintValidator, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, dedupeCacheKeys, duplicateIndex, emptyIndex, errorRateOutlier, errorWithoutCatalog, exportSinkMisconfigured, externalSourceIncrementalNoDeletePath, externalSourceOnGlobal, externalSourceUnscoped, fanOutBreadth, filterOnPrimaryKey, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, fromServerSchema, geoIndexFieldNotGeopoint, geoIndexUnused, globalTableNearColumnLimit, gradeFromScore, hardcodedSecret, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, kvUnscopedUserKeyIdor, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, notifyMissingPushConfig, notifySendOutsideAction, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, parseAdvisorMap, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, procedureWithoutStructuredEvent, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, scoreAdvisor, shapeTargetsGlobalTable, shapeUnknownTable, signupMutationWithoutDisposableGating, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, ttlFieldNotTimestamp, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, unrestrictedWhereBranch, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
4658
+ export { ALL_LINTS, type AdvisorAdminRoute, type AdvisorAiRawRun, type AdvisorAiToolSideEffect, type AdvisorArgumentDerivedFetch, type AdvisorArgumentValidator, type AdvisorAuthApiCall, type AdvisorAuthConfig, type AdvisorBrowserUrlAccess, type AdvisorConfigCall, type AdvisorContainer, type AdvisorContainerKeyAccess, type AdvisorContainerOverride, type AdvisorExportSink, type AdvisorFailOpenGuard, type AdvisorFlagRead, type AdvisorFlagSecurityDefault, type AdvisorFunctionMetrics, type AdvisorGeoIndexUsage, type AdvisorHttpActionGuard, type AdvisorHttpHeaderWrite, type AdvisorHyperdriveCall, type AdvisorIdentityClaimRead, type AdvisorImageDeliveryUrlAccess, type AdvisorIndex, type AdvisorIndexHit, type AdvisorInsertWrite, type AdvisorKvKeyAccess, type AdvisorMailRecipientAccess, type AdvisorMap, type AdvisorMaskProcedure, type AdvisorMaskStrategy, type AdvisorMutatorWrite, type AdvisorNondeterministicCall, type AdvisorNormalizeIdAuthorization, type AdvisorNotifyCall, type AdvisorNotifyConfig, type AdvisorOwnerFieldWrite, type AdvisorPaymentWebhook, type AdvisorPrivilegedDispatch, type AdvisorProcedureProtection, type AdvisorQueryRead, type AdvisorQueue, type AdvisorQueueTuning, type AdvisorR2sqlCall, type AdvisorRatelimitKeySelector, type AdvisorRawRowReturn, type AdvisorRelation, type AdvisorRelationLoad, type AdvisorRlsProcedure, type AdvisorSchema, type AdvisorSecretLiteral, type AdvisorShape, type AdvisorShardTraffic, type AdvisorSoftDeleteRead, type AdvisorSqlInterpolation, type AdvisorStaleMigrationImport, type AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableSample, type AdvisorTableScan, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type BaselineComparison, type Category, type CheckResult, type Coverage, type Facing, type Finding, type Grade, type Level, type Lint, type LintContext, type LintSource, MAP_VERSION, type MapSummary, type ProcedureDelta, type ProcedureScore, type ProjectScore, RUNTIME_LINTS, RunAdvisorOptions, STATIC_LINTS, type ScoreAdvisorOptions, type Sensitivity, type SensitivityLevel, actionFetchSsrf, actionWithoutErrorHandling, adminRouteWithoutGuard, aiRawRunEscapeHatch, aiRunWithoutLogging, aiToolSideEffectPromptInjection, aiUnboundedGenerationPublic, allowUnauthenticatedShardAccessEnabled, authApiCallWithoutHeaders, authCsrfCheckDisabled, authEmailVerificationDisabled, authScimWithoutTransactions, authSecureCookiesDisabled, authSessionFreshageZero, authTrustedOriginsWildcard, browserAllowPrivateTargets, browserUserUrlWithoutAllowlist, byCodepoint, circularFk, classifySensitivity, commitOrderedHardDelete, compareToBaseline, constraintValidator, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, dedupeCacheKeys, duplicateIndex, emptyIndex, errorRateOutlier, errorWithoutCatalog, exportSinkMisconfigured, externalSourceIncrementalNoDeletePath, externalSourceOnGlobal, externalSourceUnscoped, fanOutBreadth, filterOnPrimaryKey, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, flagReadInSubscription, fromServerSchema, geoIndexFieldNotGeopoint, geoIndexUnused, globalTableNearColumnLimit, gradeFromScore, hardcodedSecret, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, kvUnscopedUserKeyIdor, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, notifyMissingPushConfig, notifySendOutsideAction, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, parseAdvisorMap, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, procedureWithoutStructuredEvent, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, scoreAdvisor, shapeTargetsGlobalTable, shapeUnknownTable, signupMutationWithoutDisposableGating, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, ttlFieldNotTimestamp, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, unrestrictedWhereBranch, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{dedupeCacheKeys as c}from"./packem_shared/dedupeCacheKeys-DtBOHffV.mjs";import d from"./packem_shared/constraintValidator-DoRJD9Is.mjs";import u from"./packem_shared/errorRateOutlier-pr3_ZKbq.mjs";import h from"./packem_shared/fanOutBreadth-CBtmZnoh.mjs";import g from"./packem_shared/hotShard-BwGYZ3Tq.mjs";import b from"./packem_shared/indexUtilization-CkVPZcVe.mjs";import y from"./packem_shared/actionFetchSsrf-Z61P0o8U.mjs";import w from"./packem_shared/actionWithoutErrorHandling-4GCBT0_z.mjs";import S from"./packem_shared/adminRouteWithoutGuard-DPE7LuNh.mjs";import v from"./packem_shared/aiRawRunEscapeHatch-Dq43DVD9.mjs";import A from"./packem_shared/aiRunWithoutLogging-CvHHtEN9.mjs";import U from"./packem_shared/aiToolSideEffectPromptInjection-K42X3QzJ.mjs";import R from"./packem_shared/aiUnboundedGenerationPublic-C17h6sMV.mjs";import W from"./packem_shared/allowUnauthenticatedShardAccessEnabled-CjXI-kda.mjs";import T from"./packem_shared/authApiCallWithoutHeaders-C1OOWML5.mjs";import I from"./packem_shared/authCsrfCheckDisabled-Dz27bDzp.mjs";import N from"./packem_shared/authEmailVerificationDisabled-QTDD7TAU.mjs";import k from"./packem_shared/authScimWithoutTransactions-FqdTmUJs.mjs";import x from"./packem_shared/authSecureCookiesDisabled-CrGYulfJ.mjs";import F from"./packem_shared/authSessionFreshageZero-yWE6CGYP.mjs";import C from"./packem_shared/authTrustedOriginsWildcard-xpeRXfGF.mjs";import O from"./packem_shared/browserAllowPrivateTargets-Cj5sizhv.mjs";import M from"./packem_shared/browserUserUrlWithoutAllowlist-Wl3xHr7v.mjs";import $ from"./packem_shared/circularFk-DtcWFJxK.mjs";import D from"./packem_shared/commitOrderedHardDelete-BPdwOKA7.mjs";import E from"./packem_shared/containerInstanceKeyFromUserInput-uEQQVsEz.mjs";import P from"./packem_shared/containerOversizedInstance-Bx89uR7E.mjs";import K from"./packem_shared/containerPublicInternet-BFfZf_P4.mjs";import q from"./packem_shared/containerRuntimeEgressRelaxation-pkpyXNou.mjs";import L from"./packem_shared/containerStartEnableInternetOverride-BBY4PMG1.mjs";import G from"./packem_shared/duplicateIndex-Cip6-Rpu.mjs";import _ from"./packem_shared/emptyIndex-BnHDcXza.mjs";import z from"./packem_shared/errorWithoutCatalog-BTfvaXHR.mjs";import H from"./packem_shared/exportSinkMisconfigured-JfbAx9AI.mjs";import B from"./packem_shared/externalSourceIncrementalNoDeletePath-BCzm3HzF.mjs";import V from"./packem_shared/externalSourceOnGlobal-CH7xbJ49.mjs";import j from"./packem_shared/externalSourceUnscoped-BxU2uSXk.mjs";import Q from"./packem_shared/filterOnPrimaryKey-COQRpmnu.mjs";import X from"./packem_shared/filterWithoutIndex-Cf-tXY_A.mjs";import Z from"./packem_shared/flagGatesSecurityWithUnsafeDefault-i-Befg8b.mjs";import J from"./packem_shared/geoIndexFieldNotGeopoint-D0lOTm-_.mjs";import Y from"./packem_shared/geoIndexUnused-D7C9Qr4U.mjs";import oo from"./packem_shared/globalTableNearColumnLimit-BFbBBd6A.mjs";import eo from"./packem_shared/hardcodedSecret-Bw_4FYrs.mjs";import ro from"./packem_shared/httpActionMissingAuthGuard-BS3JZgaz.mjs";import to from"./packem_shared/httpActionResponseHeaderInjection-DHnc8c9f.mjs";import io from"./packem_shared/hyperdriveOutsideAction-CPDdGP2g.mjs";import no from"./packem_shared/identityUndeclaredClaimTrusted-BDFqB7Dw.mjs";import ao from"./packem_shared/imagesUrlSourceFromUserInput-DizsRh3M.mjs";import mo from"./packem_shared/indexReferencesUnknownField-B_c3o9QR.mjs";import so from"./packem_shared/insertManyUnsafeUserData-DWE8d_DF.mjs";import lo from"./packem_shared/kvUnscopedUserKeyIdor-CIgMPzFj.mjs";import po from"./packem_shared/mailInboundDispatchWithoutVerify-CWwqXyPX.mjs";import fo from"./packem_shared/mailRecipientFromRequestInput-SDCchLP7.mjs";import co from"./packem_shared/maskUncoveredPiiColumn-axEka4nd.mjs";import uo from"./packem_shared/maskWeakHashStrategyOnPii-BC1n0F4-.mjs";import ho from"./packem_shared/maskedRelationLeakViaWith-C8n-Mzb1.mjs";import{e as a}from"./packem_shared/finding-NrKO8idM.mjs";import go from"./packem_shared/mutatorFullRowReplace-BzRpZ47r.mjs";import bo from"./packem_shared/nondeterministicQueryMutation-sxmixc0l.mjs";import yo from"./packem_shared/normalizeIdUsedAsAuthorization-BXN-Can6.mjs";import wo from"./packem_shared/notifyMissingPushConfig-DeQMoNwm.mjs";import So from"./packem_shared/notifySendOutsideAction-CU4T16cR.mjs";import vo from"./packem_shared/outputProjectionMissingOnPublicRead-BZI8Y7am.mjs";import Ao from"./packem_shared/ownerFieldFromArgsNotAuth-CjOSUDKi.mjs";import Uo from"./packem_shared/paymentCreateWithoutAuthorize-CICGmRFR.mjs";import Ro from"./packem_shared/paymentWebhookWideTolerance-B-F5jOeA.mjs";import Wo from"./packem_shared/plaintextSecretInWranglerVariables-bNkqmNqV.mjs";import To from"./packem_shared/policyReferencesUnknownTable-CIKuRZ5Y.mjs";import Io from"./packem_shared/privilegedDispatchUnvalidatedPayload-C6Qtc8aT.mjs";import No from"./packem_shared/privilegedFanoutFromPublicProcedure-Coqt23CQ.mjs";import ko from"./packem_shared/procedureWithoutStructuredEvent-CZ_B23nM.mjs";import xo from"./packem_shared/publicArgumentUsesAny-BDEvMA8Q.mjs";import Fo from"./packem_shared/publicMutationWithoutRatelimit-Dsd4cSPD.mjs";import Co from"./packem_shared/publicTableRlsOptoutConfusion-Dz7lbKKe.mjs";import Oo from"./packem_shared/queueWithoutDlq-BvHz3Opg.mjs";import Mo from"./packem_shared/r2sqlOutsideAction-BdLiLOAX.mjs";import $o from"./packem_shared/ratelimitDefaultMemoryStore-Dj0Kk7t9.mjs";import Do from"./packem_shared/ratelimitKeySpoofableOrGlobal-BzDzxnXm.mjs";import Eo from"./packem_shared/ratelimitMiddlewareFailOpen-iDJq68qx.mjs";import Po from"./packem_shared/relationReferencesUnknownField-D8Qyth_P.mjs";import Ko from"./packem_shared/relationReferencesUnknownTable-CP4aWtAJ.mjs";import qo from"./packem_shared/rlsUncoveredTable-CZ4ie4gX.mjs";import Lo from"./packem_shared/shapeTargetsGlobalTable-Bu3eEDic.mjs";import Go from"./packem_shared/shapeUnknownTable-CREfNnWi.mjs";import _o from"./packem_shared/signupMutationWithoutDisposableGating-BIsSLyhJ.mjs";import zo from"./packem_shared/softDeleteIncludeDeletedFromArgs-C7Ugg4zb.mjs";import Ho from"./packem_shared/sqlInjectionRisk-CslaRBxz.mjs";import Bo from"./packem_shared/storageGenerateUploadUrlNoContentTypePin-CTIU_7Fj.mjs";import Vo from"./packem_shared/storageKeyFromUserArgs-C-QUcdJ3.mjs";import jo from"./packem_shared/storagePresignedUrlForPrivateContent-yeu1s81k.mjs";import Qo from"./packem_shared/storageUploadWithoutContentTypeAllowlist-KSRG81Iu.mjs";import Xo from"./packem_shared/storageUploadWithoutMaxSize-BTiM9Q3A.mjs";import Zo from"./packem_shared/tableWithoutInsert-DQ-GxjFF.mjs";import Jo from"./packem_shared/ttlFieldNotTimestamp-E14I83wY.mjs";import{s as Yo,q as oe}from"./packem_shared/helpers-CwSEZdku.mjs";import ee from"./packem_shared/unboundedStringArgument-DzbFJc5q.mjs";import re from"./packem_shared/unindexedForeignKey-Dypgn8uH.mjs";import te from"./packem_shared/unindexedRelationTarget-CSqRJWYZ.mjs";import ie from"./packem_shared/unrestrictedWhereBranch-CcIBmHik.mjs";import ne from"./packem_shared/userCreatingMutationWithoutCaptcha-B7l-S-rV.mjs";import ae from"./packem_shared/vectorsNamespaceFromUserInput-CDSOrkyX.mjs";import me from"./packem_shared/workflowDuplicateStepName-BU4rg5So.mjs";import se from"./packem_shared/workflowUnknownTarget-B8H7jwnH.mjs";import le from"./packem_shared/workflowUnused-BUSOPdHq.mjs";import{compareToBaseline as gt,parseAdvisorMap as bt}from"./packem_shared/compareToBaseline-DBgN5YqX.mjs";import{gradeFromScore as wt}from"./packem_shared/gradeFromScore-KSt58rj1.mjs";import{MAP_VERSION as vt,byCodepoint as At,scoreAdvisor as Ut}from"./packem_shared/MAP_VERSION-DEJGm0wI.mjs";import{default as Wt}from"./packem_shared/classifySensitivity-JnjaTGYi.mjs";import{fromServerSchema as It}from"./packem_shared/fromServerSchema-D2nTknz0.mjs";const pe={convex:"migrating/from-convex",firebase:"migrating/from-firebase",supabase:"migrating/from-supabase"},m={categories:["SCHEMA"],description:"A migrated-away platform's SDK is still imported from `lunora/` source. The code compiles and typechecks, so a half-finished port keeps reading from the old platform at runtime and the two stores silently drift apart.",facing:"INTERNAL",level:"WARN",name:"migration_stale_import",remediation:"Replace the call with its Lunora equivalent and drop the dependency. If the import is deliberate — a second data source you still read from — move it out of `lunora/` so it is not mistaken for an unfinished migration.",run:r=>r.staleMigrationImports===void 0?[]:r.staleMigrationImports.map(o=>a(m,{cacheKey:`migration_stale_import:${o.file}:${o.line.toString()}:${o.moduleSpecifier}`,detail:`\`${o.file}\` (line ${o.line.toString()}) still imports \`${o.moduleSpecifier}\`. Finish the port — see \`${pe[o.platform]}\` — or move the import out of \`lunora/\` if you genuinely still read from ${o.platform}.`,metadata:{file:o.file,line:o.line,moduleSpecifier:o.moduleSpecifier,platform:o.platform}})),source:"static",title:"Stale migration import"},fe=new Map([["global",{level:"WARN",scope:r=>`it reads the whole D1 table "${r}" over a cross-region round trip`}],["root",{level:"WARN",scope:r=>`it loads every row of "${r}" from the root Durable Object's SQLite into memory`}],["shardBy",{level:"INFO",scope:r=>`"${r}" is \`.shardBy()\`, so this collects one shard's rows rather than the whole table — bounded by a single tenant's row count`}]]),ce={level:"WARN",scope:r=>`it loads every row of "${r}"`},s={categories:["PERFORMANCE"],description:"A query calls `.collect()` with no `.withIndex()` and no `.filter()`, so it materializes every row of the table. Any live subscription over it also re-sends that whole result to every subscribed client on every write to the table.",facing:"EXTERNAL",level:"WARN",name:"unbounded_collect",remediation:'Narrow the read with `.withIndex("name", (q) => q.eq(...))`, cap it with `.take(n)`, or page it with `.paginate(args.paginationOpts)` so neither the scan nor the subscription payload grows with the table.',run:r=>{const o=[],i=Yo(r.schema);for(const e of r.queries??[]){if(e.terminal!=="collect"||e.hasIndex||e.table===""||e.hasFilter)continue;const t=i.get(e.table),{level:n,scope:l}=fe.get(t??"")??ce,p=oe(e),f=n==="WARN"?` A live subscription over this query records a whole-table dependency, so every write to "${e.table}" re-runs it and re-sends the full result to each subscribed socket.`:" Cap it with `.take(n)` if that count can grow.";o.push(a(s,{cacheKey:`unbounded_collect:${e.file}:${e.line.toString()}:${e.table}`,detail:`Query on "${e.table}" at ${p} calls .collect() with no index and no filter — ${l(e.table)}.${f}`,level:n,metadata:{exportName:e.exportName,file:e.file,line:e.line,shardKind:t??"unknown",table:e.table}}))}return o},source:"static",title:"Unbounded collect"},de=[mo,Ko,Po,se,me,Go,B,V,j,_,oo,z,J,Y,H,Jo,D,$,re,te,G,Zo,le,Oo,Q,X,s,Lo,go,bo,io,Mo,T,To,qo,co,uo,P,K,Fo,ie,ne,_o,xo,ee,eo,Ho,S,Uo,po,$o,O,No,ko,so,R,y,w,Ao,Vo,lo,E,v,A,ae,fo,M,Io,L,q,k,C,I,x,N,F,ao,Do,Co,W,Qo,Xo,Bo,jo,ro,to,Eo,Z,U,no,Ro,zo,ho,vo,yo,So,wo,Wo,m],ue=[g,b,d,u,h],he=[...de,...ue],dt=(r,o={})=>{const i=o.lints??he,e=[];for(const t of i)o.source!==void 0&&t.source!==o.source||e.push(...t.run(r));return c(e)};export{he as ALL_LINTS,vt as MAP_VERSION,ue as RUNTIME_LINTS,de as STATIC_LINTS,y as actionFetchSsrf,w as actionWithoutErrorHandling,S as adminRouteWithoutGuard,v as aiRawRunEscapeHatch,A as aiRunWithoutLogging,U as aiToolSideEffectPromptInjection,R as aiUnboundedGenerationPublic,W as allowUnauthenticatedShardAccessEnabled,T as authApiCallWithoutHeaders,I as authCsrfCheckDisabled,N as authEmailVerificationDisabled,k as authScimWithoutTransactions,x as authSecureCookiesDisabled,F as authSessionFreshageZero,C as authTrustedOriginsWildcard,O as browserAllowPrivateTargets,M as browserUserUrlWithoutAllowlist,At as byCodepoint,$ as circularFk,Wt as classifySensitivity,D as commitOrderedHardDelete,gt as compareToBaseline,d as constraintValidator,E as containerInstanceKeyFromUserInput,P as containerOversizedInstance,K as containerPublicInternet,q as containerRuntimeEgressRelaxation,L as containerStartEnableInternetOverride,c as dedupeCacheKeys,G as duplicateIndex,_ as emptyIndex,u as errorRateOutlier,z as errorWithoutCatalog,H as exportSinkMisconfigured,B as externalSourceIncrementalNoDeletePath,V as externalSourceOnGlobal,j as externalSourceUnscoped,h as fanOutBreadth,Q as filterOnPrimaryKey,X as filterWithoutIndex,Z as flagGatesSecurityWithUnsafeDefault,It as fromServerSchema,J as geoIndexFieldNotGeopoint,Y as geoIndexUnused,oo as globalTableNearColumnLimit,wt as gradeFromScore,eo as hardcodedSecret,g as hotShard,ro as httpActionMissingAuthGuard,to as httpActionResponseHeaderInjection,io as hyperdriveOutsideAction,no as identityUndeclaredClaimTrusted,ao as imagesUrlSourceFromUserInput,mo as indexReferencesUnknownField,b as indexUtilization,so as insertManyUnsafeUserData,lo as kvUnscopedUserKeyIdor,po as mailInboundDispatchWithoutVerify,fo as mailRecipientFromRequestInput,co as maskUncoveredPiiColumn,uo as maskWeakHashStrategyOnPii,ho as maskedRelationLeakViaWith,go as mutatorFullRowReplace,bo as nondeterministicQueryMutation,yo as normalizeIdUsedAsAuthorization,wo as notifyMissingPushConfig,So as notifySendOutsideAction,vo as outputProjectionMissingOnPublicRead,Ao as ownerFieldFromArgsNotAuth,bt as parseAdvisorMap,Uo as paymentCreateWithoutAuthorize,Ro as paymentWebhookWideTolerance,Wo as plaintextSecretInWranglerVariables,To as policyReferencesUnknownTable,Io as privilegedDispatchUnvalidatedPayload,No as privilegedFanoutFromPublicProcedure,ko as procedureWithoutStructuredEvent,xo as publicArgumentUsesAny,Fo as publicMutationWithoutRatelimit,Co as publicTableRlsOptoutConfusion,Oo as queueWithoutDlq,Mo as r2sqlOutsideAction,$o as ratelimitDefaultMemoryStore,Do as ratelimitKeySpoofableOrGlobal,Eo as ratelimitMiddlewareFailOpen,Po as relationReferencesUnknownField,Ko as relationReferencesUnknownTable,qo as rlsUncoveredTable,dt as runAdvisor,Ut as scoreAdvisor,Lo as shapeTargetsGlobalTable,Go as shapeUnknownTable,_o as signupMutationWithoutDisposableGating,zo as softDeleteIncludeDeletedFromArgs,Ho as sqlInjectionRisk,Bo as storageGenerateUploadUrlNoContentTypePin,Vo as storageKeyFromUserArgs,jo as storagePresignedUrlForPrivateContent,Qo as storageUploadWithoutContentTypeAllowlist,Xo as storageUploadWithoutMaxSize,Zo as tableWithoutInsert,Jo as ttlFieldNotTimestamp,ee as unboundedStringArgument,re as unindexedForeignKey,te as unindexedRelationTarget,ie as unrestrictedWhereBranch,ne as userCreatingMutationWithoutCaptcha,ae as vectorsNamespaceFromUserInput,me as workflowDuplicateStepName,se as workflowUnknownTarget,le as workflowUnused};
1
+ import{dedupeCacheKeys as c}from"./packem_shared/dedupeCacheKeys-DtBOHffV.mjs";import d from"./packem_shared/constraintValidator-DoRJD9Is.mjs";import u from"./packem_shared/errorRateOutlier-pr3_ZKbq.mjs";import h from"./packem_shared/fanOutBreadth-CBtmZnoh.mjs";import g from"./packem_shared/hotShard-BwGYZ3Tq.mjs";import b from"./packem_shared/indexUtilization-CkVPZcVe.mjs";import y from"./packem_shared/actionFetchSsrf-Z61P0o8U.mjs";import w from"./packem_shared/actionWithoutErrorHandling-4GCBT0_z.mjs";import S from"./packem_shared/adminRouteWithoutGuard-DPE7LuNh.mjs";import v from"./packem_shared/aiRawRunEscapeHatch-Dq43DVD9.mjs";import A from"./packem_shared/aiRunWithoutLogging-CvHHtEN9.mjs";import R from"./packem_shared/aiToolSideEffectPromptInjection-K42X3QzJ.mjs";import U from"./packem_shared/aiUnboundedGenerationPublic-C17h6sMV.mjs";import W from"./packem_shared/allowUnauthenticatedShardAccessEnabled-CjXI-kda.mjs";import T from"./packem_shared/authApiCallWithoutHeaders-C1OOWML5.mjs";import I from"./packem_shared/authCsrfCheckDisabled-Dz27bDzp.mjs";import N from"./packem_shared/authEmailVerificationDisabled-QTDD7TAU.mjs";import k from"./packem_shared/authScimWithoutTransactions-FqdTmUJs.mjs";import x from"./packem_shared/authSecureCookiesDisabled-CrGYulfJ.mjs";import F from"./packem_shared/authSessionFreshageZero-yWE6CGYP.mjs";import C from"./packem_shared/authTrustedOriginsWildcard-xpeRXfGF.mjs";import O from"./packem_shared/browserAllowPrivateTargets-Cj5sizhv.mjs";import M from"./packem_shared/browserUserUrlWithoutAllowlist-Wl3xHr7v.mjs";import $ from"./packem_shared/circularFk-DtcWFJxK.mjs";import D from"./packem_shared/commitOrderedHardDelete-BPdwOKA7.mjs";import E from"./packem_shared/containerInstanceKeyFromUserInput-uEQQVsEz.mjs";import P from"./packem_shared/containerOversizedInstance-Bx89uR7E.mjs";import K from"./packem_shared/containerPublicInternet-BFfZf_P4.mjs";import q from"./packem_shared/containerRuntimeEgressRelaxation-pkpyXNou.mjs";import L from"./packem_shared/containerStartEnableInternetOverride-BBY4PMG1.mjs";import G from"./packem_shared/duplicateIndex-Cip6-Rpu.mjs";import _ from"./packem_shared/emptyIndex-BnHDcXza.mjs";import z from"./packem_shared/errorWithoutCatalog-BTfvaXHR.mjs";import H from"./packem_shared/exportSinkMisconfigured-JfbAx9AI.mjs";import B from"./packem_shared/externalSourceIncrementalNoDeletePath-BCzm3HzF.mjs";import V from"./packem_shared/externalSourceOnGlobal-CH7xbJ49.mjs";import j from"./packem_shared/externalSourceUnscoped-BxU2uSXk.mjs";import Q from"./packem_shared/filterOnPrimaryKey-COQRpmnu.mjs";import X from"./packem_shared/filterWithoutIndex-Cf-tXY_A.mjs";import Z from"./packem_shared/flagGatesSecurityWithUnsafeDefault-i-Befg8b.mjs";import J from"./packem_shared/flagReadInSubscription-DabIhYGD.mjs";import Y from"./packem_shared/geoIndexFieldNotGeopoint-D0lOTm-_.mjs";import oo from"./packem_shared/geoIndexUnused-D7C9Qr4U.mjs";import eo from"./packem_shared/globalTableNearColumnLimit-BFbBBd6A.mjs";import ro from"./packem_shared/hardcodedSecret-Bw_4FYrs.mjs";import to from"./packem_shared/httpActionMissingAuthGuard-BS3JZgaz.mjs";import io from"./packem_shared/httpActionResponseHeaderInjection-DHnc8c9f.mjs";import no from"./packem_shared/hyperdriveOutsideAction-CPDdGP2g.mjs";import ao from"./packem_shared/identityUndeclaredClaimTrusted-BDFqB7Dw.mjs";import mo from"./packem_shared/imagesUrlSourceFromUserInput-DizsRh3M.mjs";import so from"./packem_shared/indexReferencesUnknownField-B_c3o9QR.mjs";import lo from"./packem_shared/insertManyUnsafeUserData-DWE8d_DF.mjs";import po from"./packem_shared/kvUnscopedUserKeyIdor-CIgMPzFj.mjs";import fo from"./packem_shared/mailInboundDispatchWithoutVerify-CWwqXyPX.mjs";import co from"./packem_shared/mailRecipientFromRequestInput-SDCchLP7.mjs";import uo from"./packem_shared/maskUncoveredPiiColumn-axEka4nd.mjs";import ho from"./packem_shared/maskWeakHashStrategyOnPii-BC1n0F4-.mjs";import go from"./packem_shared/maskedRelationLeakViaWith-C8n-Mzb1.mjs";import{e as a}from"./packem_shared/finding-NrKO8idM.mjs";import bo from"./packem_shared/mutatorFullRowReplace-BzRpZ47r.mjs";import yo from"./packem_shared/nondeterministicQueryMutation-sxmixc0l.mjs";import wo from"./packem_shared/normalizeIdUsedAsAuthorization-BXN-Can6.mjs";import So from"./packem_shared/notifyMissingPushConfig-DeQMoNwm.mjs";import vo from"./packem_shared/notifySendOutsideAction-CU4T16cR.mjs";import Ao from"./packem_shared/outputProjectionMissingOnPublicRead-BZI8Y7am.mjs";import Ro from"./packem_shared/ownerFieldFromArgsNotAuth-CjOSUDKi.mjs";import Uo from"./packem_shared/paymentCreateWithoutAuthorize-CICGmRFR.mjs";import Wo from"./packem_shared/paymentWebhookWideTolerance-B-F5jOeA.mjs";import To from"./packem_shared/plaintextSecretInWranglerVariables-bNkqmNqV.mjs";import Io from"./packem_shared/policyReferencesUnknownTable-CIKuRZ5Y.mjs";import No from"./packem_shared/privilegedDispatchUnvalidatedPayload-C6Qtc8aT.mjs";import ko from"./packem_shared/privilegedFanoutFromPublicProcedure-Coqt23CQ.mjs";import xo from"./packem_shared/procedureWithoutStructuredEvent-CZ_B23nM.mjs";import Fo from"./packem_shared/publicArgumentUsesAny-BDEvMA8Q.mjs";import Co from"./packem_shared/publicMutationWithoutRatelimit-Dsd4cSPD.mjs";import Oo from"./packem_shared/publicTableRlsOptoutConfusion-Dz7lbKKe.mjs";import Mo from"./packem_shared/queueWithoutDlq-BvHz3Opg.mjs";import $o from"./packem_shared/r2sqlOutsideAction-BdLiLOAX.mjs";import Do from"./packem_shared/ratelimitDefaultMemoryStore-Dj0Kk7t9.mjs";import Eo from"./packem_shared/ratelimitKeySpoofableOrGlobal-BzDzxnXm.mjs";import Po from"./packem_shared/ratelimitMiddlewareFailOpen-iDJq68qx.mjs";import Ko from"./packem_shared/relationReferencesUnknownField-D8Qyth_P.mjs";import qo from"./packem_shared/relationReferencesUnknownTable-CP4aWtAJ.mjs";import Lo from"./packem_shared/rlsUncoveredTable-CZ4ie4gX.mjs";import Go from"./packem_shared/shapeTargetsGlobalTable-Bu3eEDic.mjs";import _o from"./packem_shared/shapeUnknownTable-CREfNnWi.mjs";import zo from"./packem_shared/signupMutationWithoutDisposableGating-BIsSLyhJ.mjs";import Ho from"./packem_shared/softDeleteIncludeDeletedFromArgs-C7Ugg4zb.mjs";import Bo from"./packem_shared/sqlInjectionRisk-CslaRBxz.mjs";import Vo from"./packem_shared/storageGenerateUploadUrlNoContentTypePin-CTIU_7Fj.mjs";import jo from"./packem_shared/storageKeyFromUserArgs-C-QUcdJ3.mjs";import Qo from"./packem_shared/storagePresignedUrlForPrivateContent-yeu1s81k.mjs";import Xo from"./packem_shared/storageUploadWithoutContentTypeAllowlist-KSRG81Iu.mjs";import Zo from"./packem_shared/storageUploadWithoutMaxSize-BTiM9Q3A.mjs";import Jo from"./packem_shared/tableWithoutInsert-DQ-GxjFF.mjs";import Yo from"./packem_shared/ttlFieldNotTimestamp-E14I83wY.mjs";import{s as oe,q as ee}from"./packem_shared/helpers-CwSEZdku.mjs";import re from"./packem_shared/unboundedStringArgument-DzbFJc5q.mjs";import te from"./packem_shared/unindexedForeignKey-Dypgn8uH.mjs";import ie from"./packem_shared/unindexedRelationTarget-CSqRJWYZ.mjs";import ne from"./packem_shared/unrestrictedWhereBranch-CcIBmHik.mjs";import ae from"./packem_shared/userCreatingMutationWithoutCaptcha-B7l-S-rV.mjs";import me from"./packem_shared/vectorsNamespaceFromUserInput-CDSOrkyX.mjs";import se from"./packem_shared/workflowDuplicateStepName-BU4rg5So.mjs";import le from"./packem_shared/workflowUnknownTarget-B8H7jwnH.mjs";import pe from"./packem_shared/workflowUnused-BUSOPdHq.mjs";import{compareToBaseline as yt,parseAdvisorMap as wt}from"./packem_shared/compareToBaseline-DBgN5YqX.mjs";import{gradeFromScore as vt}from"./packem_shared/gradeFromScore-KSt58rj1.mjs";import{MAP_VERSION as Rt,byCodepoint as Ut,scoreAdvisor as Wt}from"./packem_shared/MAP_VERSION-DEJGm0wI.mjs";import{default as It}from"./packem_shared/classifySensitivity-JnjaTGYi.mjs";import{fromServerSchema as kt}from"./packem_shared/fromServerSchema-D2nTknz0.mjs";const fe={convex:"migrating/from-convex",firebase:"migrating/from-firebase",supabase:"migrating/from-supabase"},m={categories:["SCHEMA"],description:"A migrated-away platform's SDK is still imported from `lunora/` source. The code compiles and typechecks, so a half-finished port keeps reading from the old platform at runtime and the two stores silently drift apart.",facing:"INTERNAL",level:"WARN",name:"migration_stale_import",remediation:"Replace the call with its Lunora equivalent and drop the dependency. If the import is deliberate — a second data source you still read from — move it out of `lunora/` so it is not mistaken for an unfinished migration.",run:r=>r.staleMigrationImports===void 0?[]:r.staleMigrationImports.map(o=>a(m,{cacheKey:`migration_stale_import:${o.file}:${o.line.toString()}:${o.moduleSpecifier}`,detail:`\`${o.file}\` (line ${o.line.toString()}) still imports \`${o.moduleSpecifier}\`. Finish the port — see \`${fe[o.platform]}\` — or move the import out of \`lunora/\` if you genuinely still read from ${o.platform}.`,metadata:{file:o.file,line:o.line,moduleSpecifier:o.moduleSpecifier,platform:o.platform}})),source:"static",title:"Stale migration import"},ce=new Map([["global",{level:"WARN",scope:r=>`it reads the whole D1 table "${r}" over a cross-region round trip`}],["root",{level:"WARN",scope:r=>`it loads every row of "${r}" from the root Durable Object's SQLite into memory`}],["shardBy",{level:"INFO",scope:r=>`"${r}" is \`.shardBy()\`, so this collects one shard's rows rather than the whole table — bounded by a single tenant's row count`}]]),de={level:"WARN",scope:r=>`it loads every row of "${r}"`},s={categories:["PERFORMANCE"],description:"A query calls `.collect()` with no `.withIndex()` and no `.filter()`, so it materializes every row of the table. Any live subscription over it also re-sends that whole result to every subscribed client on every write to the table.",facing:"EXTERNAL",level:"WARN",name:"unbounded_collect",remediation:'Narrow the read with `.withIndex("name", (q) => q.eq(...))`, cap it with `.take(n)`, or page it with `.paginate(args.paginationOpts)` so neither the scan nor the subscription payload grows with the table.',run:r=>{const o=[],i=oe(r.schema);for(const e of r.queries??[]){if(e.terminal!=="collect"||e.hasIndex||e.table===""||e.hasFilter)continue;const t=i.get(e.table),{level:n,scope:l}=ce.get(t??"")??de,p=ee(e),f=n==="WARN"?` A live subscription over this query records a whole-table dependency, so every write to "${e.table}" re-runs it and re-sends the full result to each subscribed socket.`:" Cap it with `.take(n)` if that count can grow.";o.push(a(s,{cacheKey:`unbounded_collect:${e.file}:${e.line.toString()}:${e.table}`,detail:`Query on "${e.table}" at ${p} calls .collect() with no index and no filter — ${l(e.table)}.${f}`,level:n,metadata:{exportName:e.exportName,file:e.file,line:e.line,shardKind:t??"unknown",table:e.table}}))}return o},source:"static",title:"Unbounded collect"},ue=[so,qo,Ko,le,se,_o,B,V,j,_,eo,z,Y,oo,H,Yo,D,$,te,ie,G,Jo,pe,Mo,Q,X,s,Go,bo,yo,no,$o,T,Io,Lo,uo,ho,P,K,Co,ne,ae,zo,Fo,re,ro,Bo,S,Uo,fo,Do,O,ko,xo,lo,U,y,w,Ro,jo,po,E,v,A,me,co,M,No,L,q,k,C,I,x,N,F,mo,Eo,Oo,W,Xo,Zo,Vo,Qo,to,io,Po,Z,J,R,ao,Wo,Ho,go,Ao,wo,vo,So,To,m],he=[g,b,d,u,h],ge=[...ue,...he],ht=(r,o={})=>{const i=o.lints??ge,e=[];for(const t of i)o.source!==void 0&&t.source!==o.source||e.push(...t.run(r));return c(e)};export{ge as ALL_LINTS,Rt as MAP_VERSION,he as RUNTIME_LINTS,ue as STATIC_LINTS,y as actionFetchSsrf,w as actionWithoutErrorHandling,S as adminRouteWithoutGuard,v as aiRawRunEscapeHatch,A as aiRunWithoutLogging,R as aiToolSideEffectPromptInjection,U as aiUnboundedGenerationPublic,W as allowUnauthenticatedShardAccessEnabled,T as authApiCallWithoutHeaders,I as authCsrfCheckDisabled,N as authEmailVerificationDisabled,k as authScimWithoutTransactions,x as authSecureCookiesDisabled,F as authSessionFreshageZero,C as authTrustedOriginsWildcard,O as browserAllowPrivateTargets,M as browserUserUrlWithoutAllowlist,Ut as byCodepoint,$ as circularFk,It as classifySensitivity,D as commitOrderedHardDelete,yt as compareToBaseline,d as constraintValidator,E as containerInstanceKeyFromUserInput,P as containerOversizedInstance,K as containerPublicInternet,q as containerRuntimeEgressRelaxation,L as containerStartEnableInternetOverride,c as dedupeCacheKeys,G as duplicateIndex,_ as emptyIndex,u as errorRateOutlier,z as errorWithoutCatalog,H as exportSinkMisconfigured,B as externalSourceIncrementalNoDeletePath,V as externalSourceOnGlobal,j as externalSourceUnscoped,h as fanOutBreadth,Q as filterOnPrimaryKey,X as filterWithoutIndex,Z as flagGatesSecurityWithUnsafeDefault,J as flagReadInSubscription,kt as fromServerSchema,Y as geoIndexFieldNotGeopoint,oo as geoIndexUnused,eo as globalTableNearColumnLimit,vt as gradeFromScore,ro as hardcodedSecret,g as hotShard,to as httpActionMissingAuthGuard,io as httpActionResponseHeaderInjection,no as hyperdriveOutsideAction,ao as identityUndeclaredClaimTrusted,mo as imagesUrlSourceFromUserInput,so as indexReferencesUnknownField,b as indexUtilization,lo as insertManyUnsafeUserData,po as kvUnscopedUserKeyIdor,fo as mailInboundDispatchWithoutVerify,co as mailRecipientFromRequestInput,uo as maskUncoveredPiiColumn,ho as maskWeakHashStrategyOnPii,go as maskedRelationLeakViaWith,bo as mutatorFullRowReplace,yo as nondeterministicQueryMutation,wo as normalizeIdUsedAsAuthorization,So as notifyMissingPushConfig,vo as notifySendOutsideAction,Ao as outputProjectionMissingOnPublicRead,Ro as ownerFieldFromArgsNotAuth,wt as parseAdvisorMap,Uo as paymentCreateWithoutAuthorize,Wo as paymentWebhookWideTolerance,To as plaintextSecretInWranglerVariables,Io as policyReferencesUnknownTable,No as privilegedDispatchUnvalidatedPayload,ko as privilegedFanoutFromPublicProcedure,xo as procedureWithoutStructuredEvent,Fo as publicArgumentUsesAny,Co as publicMutationWithoutRatelimit,Oo as publicTableRlsOptoutConfusion,Mo as queueWithoutDlq,$o as r2sqlOutsideAction,Do as ratelimitDefaultMemoryStore,Eo as ratelimitKeySpoofableOrGlobal,Po as ratelimitMiddlewareFailOpen,Ko as relationReferencesUnknownField,qo as relationReferencesUnknownTable,Lo as rlsUncoveredTable,ht as runAdvisor,Wt as scoreAdvisor,Go as shapeTargetsGlobalTable,_o as shapeUnknownTable,zo as signupMutationWithoutDisposableGating,Ho as softDeleteIncludeDeletedFromArgs,Bo as sqlInjectionRisk,Vo as storageGenerateUploadUrlNoContentTypePin,jo as storageKeyFromUserArgs,Qo as storagePresignedUrlForPrivateContent,Xo as storageUploadWithoutContentTypeAllowlist,Zo as storageUploadWithoutMaxSize,Jo as tableWithoutInsert,Yo as ttlFieldNotTimestamp,re as unboundedStringArgument,te as unindexedForeignKey,ie as unindexedRelationTarget,ne as unrestrictedWhereBranch,ae as userCreatingMutationWithoutCaptcha,me as vectorsNamespaceFromUserInput,se as workflowDuplicateStepName,le as workflowUnknownTarget,pe as workflowUnused};
@@ -0,0 +1 @@
1
+ import{e as l}from"./finding-NrKO8idM.mjs";const c={categories:["SCHEMA"],description:"A `query` handler reads a feature flag via `ctx.flags`. Flag changes are invisible to the change feed — flipping a flag appends nothing to `__cdc_log` — so no live subscription re-runs and the query keeps serving the branch it picked when it last ran. The staleness produces no error and no reconnect, so it surfaces nowhere at runtime.",facing:"EXTERNAL",level:"WARN",name:"flag_read_in_subscription",remediation:"A flag read inside a query is evaluated once per query run and will NOT update when the flag flips — subscribers keep the old branch until something else invalidates the query. For a flag whose value must reach a live client, subscribe to it directly with `useFlag(...)`, which is served on the reactive flag path and re-evaluated on every write-flush, and branch in the component. If the query genuinely wants a point-in-time evaluation (a gate read once at call time), the read is correct as written and the finding can be dismissed.",run:n=>{if(n.flagReads===void 0)return[];const t=[],r=new Map;for(const e of n.flagReads){const a=`${e.file}:${e.line.toString()}:${e.callee}`,i=(r.get(a)??0)+1;r.set(a,i);const s=i>1?`:${i.toString()}`:"";t.push(l(c,{cacheKey:`flag_read_in_subscription:${a}${s}`,detail:`\`${e.callee}(…)\` in ${e.exportName} (${e.file}:${e.line.toString()}) reads a feature flag inside a query handler. The read is evaluated once per query run: flipping the flag appends nothing to the change feed, so no live subscription re-runs and subscribers keep the branch this query last picked. Subscribe with \`useFlag\` on the client if the value must stay live.`,metadata:{callee:e.callee,exportName:e.exportName,file:e.file,line:e.line}}))}return t},source:"static",title:"Feature-flag read inside a live query"};export{c as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/advisor",
3
- "version": "1.0.0-alpha.88",
3
+ "version": "1.0.0-alpha.89",
4
4
  "description": "Schema & query lints (splinter-style advisors) for Lunora, feeding the Studio Advisors view",
5
5
  "keywords": [
6
6
  "advisor",
@@ -46,8 +46,8 @@
46
46
  "access": "public"
47
47
  },
48
48
  "dependencies": {
49
- "@lunora/errors": "1.0.0-alpha.22",
50
- "@lunora/server": "1.0.0-alpha.82"
49
+ "@lunora/errors": "1.0.0-alpha.23",
50
+ "@lunora/server": "1.0.0-alpha.83"
51
51
  },
52
52
  "engines": {
53
53
  "node": "^22.15.0 || >=24.11.0"