@lunora/advisor 1.0.0-alpha.210 → 1.0.0-alpha.211

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
@@ -1605,14 +1605,30 @@ interface AdvisorExternalSource {
1605
1605
  * the holding table; for `many` it lives on the target. `name` is the accessor
1606
1606
  * the relation is loaded under.
1607
1607
  */
1608
- interface AdvisorRelation {
1608
+ interface AdvisorKeyedRelation {
1609
1609
  field: string;
1610
1610
  kind: "many" | "one";
1611
1611
  name: string;
1612
1612
  onDelete?: "cascade" | "restrict" | "set null";
1613
1613
  references: string;
1614
1614
  table: string;
1615
+ through?: never;
1615
1616
  }
1617
+ /**
1618
+ * A many-to-many relation (`r.many(target, { through })`): the link lives in the `through.table` join table,
1619
+ * whose `from` column points at the declaring table and `to` at `table`. It has no `field` of its own.
1620
+ */
1621
+ interface AdvisorThroughRelation {
1622
+ kind: "many";
1623
+ name: string;
1624
+ table: string;
1625
+ through: {
1626
+ from: string;
1627
+ table: string;
1628
+ to: string;
1629
+ };
1630
+ }
1631
+ type AdvisorRelation = AdvisorKeyedRelation | AdvisorThroughRelation;
1616
1632
  /**
1617
1633
  * Adapt the runtime `@lunora/server` {@link Schema} into an {@link AdvisorSchema}.
1618
1634
  * Runtime callers (the studio backend, a live shard) hold the real schema
@@ -4569,6 +4585,17 @@ declare const storageUploadWithoutMaxSize: Lint;
4569
4585
  * a runtime caller with no insert signal flags nothing rather than every table.
4570
4586
  */
4571
4587
  declare const tableWithoutInsert: Lint;
4588
+ /**
4589
+ * A correctness lint for many-to-many relations: the join table behind
4590
+ * `r.many(target, { through: { table, from, to } })` must carry a unique index over
4591
+ * exactly `(from, to)`.
4592
+ *
4593
+ * Without it a link is not a single row: a repeated `connect` stores the same pair
4594
+ * twice, and every read through the relation then returns the target twice. The
4595
+ * index is also what makes `set` a diff rather than a rewrite. `defineSchema` throws
4596
+ * on the same condition at load; this reports it at codegen time, before the app runs.
4597
+ */
4598
+ declare const throughRelationMissingUniqueIndex: Lint;
4572
4599
  /**
4573
4600
  * Flags a topic with more than {@link MAX_SUBSCRIPTIONS} subscriptions.
4574
4601
  *
@@ -5109,4 +5136,4 @@ interface RunAdvisorOptions {
5109
5136
  * `static` lints at build time and defer `runtime` lints to a live shard.
5110
5137
  */
5111
5138
  declare const runAdvisor: (context: LintContext, options?: RunAdvisorOptions) => Finding[];
5112
- export { ALL_LINTS, type AdvisorAdminRoute, type AdvisorAiRawRun, type AdvisorAiToolSideEffect, type AdvisorArgumentDerivedFetch, type AdvisorArgumentValidator, type AdvisorAuthApiCall, type AdvisorAuthConfig, type AdvisorBrowserUrlAccess, type AdvisorCallEdge, type AdvisorCallSiteScope, type AdvisorConfigCall, type AdvisorContainer, type AdvisorContainerKeyAccess, type AdvisorContainerOverride, type AdvisorExportSink, type AdvisorFailOpenGuard, type AdvisorFlagRead, type AdvisorFlagSecurityDefault, 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 AdvisorModule, type AdvisorMutatorDeclaration, 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 AdvisorRowEffect, type AdvisorSchema, type AdvisorSecretLiteral, type AdvisorShape, type AdvisorShardTraffic, type AdvisorSoftDeleteRead, type AdvisorSqlInterpolation, type AdvisorStaleMigrationImport, type AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableScan, type AdvisorTableWrite, type AdvisorUnboundedLoop, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type BaselineComparison, type CallSiteMetadata, 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, callSiteCallers, callSiteDescription, callSiteLabel, callSiteMetadata, circularFk, classifySensitivity, commitOrderedHardDelete, compareToBaseline, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, crossModuleTableWrite, dedupeCacheKeys, dispatchCycle, duplicateIndex, emptyIndex, errorWithoutCatalog, exportSinkMisconfigured, externalSourceIncrementalNoDeletePath, externalSourceOnGlobal, externalSourceUnscoped, fanOutBreadth, filterAfterIndexScan, filterOnPrimaryKey, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, flagReadInSubscription, fromServerSchema, geoIndexFieldNotGeopoint, geoIndexUnused, globalTableNearColumnLimit, gradeFromScore, hardcodedSecret, helperRole, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, isReachableSite, kvUnscopedUserKeyIdor, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, mutatorWithoutOwnerScope, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, notifyMissingPushConfig, notifySendOutsideAction, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, parseAdvisorMap, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, procedureWithoutStructuredEvent, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, readCallSiteCallers, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, scoreAdvisor, selfRescheduleWithoutProgress, shapeTargetsGlobalTable, shapeUnknownTable, signupMutationWithoutDisposableGating, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, topicTooManySubscriptions, ttlFieldNotTimestamp, unboundedCollectOnOpenRange, unboundedLoop, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, unrestrictedWhereBranch, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
5139
+ export { ALL_LINTS, type AdvisorAdminRoute, type AdvisorAiRawRun, type AdvisorAiToolSideEffect, type AdvisorArgumentDerivedFetch, type AdvisorArgumentValidator, type AdvisorAuthApiCall, type AdvisorAuthConfig, type AdvisorBrowserUrlAccess, type AdvisorCallEdge, type AdvisorCallSiteScope, type AdvisorConfigCall, type AdvisorContainer, type AdvisorContainerKeyAccess, type AdvisorContainerOverride, type AdvisorExportSink, type AdvisorFailOpenGuard, type AdvisorFlagRead, type AdvisorFlagSecurityDefault, type AdvisorGeoIndexUsage, type AdvisorHttpActionGuard, type AdvisorHttpHeaderWrite, type AdvisorHyperdriveCall, type AdvisorIdentityClaimRead, type AdvisorImageDeliveryUrlAccess, type AdvisorIndex, type AdvisorIndexHit, type AdvisorInsertWrite, type AdvisorKeyedRelation, type AdvisorKvKeyAccess, type AdvisorMailRecipientAccess, type AdvisorMap, type AdvisorMaskProcedure, type AdvisorMaskStrategy, type AdvisorModule, type AdvisorMutatorDeclaration, 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 AdvisorRowEffect, type AdvisorSchema, type AdvisorSecretLiteral, type AdvisorShape, type AdvisorShardTraffic, type AdvisorSoftDeleteRead, type AdvisorSqlInterpolation, type AdvisorStaleMigrationImport, type AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableScan, type AdvisorTableWrite, type AdvisorThroughRelation, type AdvisorUnboundedLoop, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type BaselineComparison, type CallSiteMetadata, 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, callSiteCallers, callSiteDescription, callSiteLabel, callSiteMetadata, circularFk, classifySensitivity, commitOrderedHardDelete, compareToBaseline, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, crossModuleTableWrite, dedupeCacheKeys, dispatchCycle, duplicateIndex, emptyIndex, errorWithoutCatalog, exportSinkMisconfigured, externalSourceIncrementalNoDeletePath, externalSourceOnGlobal, externalSourceUnscoped, fanOutBreadth, filterAfterIndexScan, filterOnPrimaryKey, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, flagReadInSubscription, fromServerSchema, geoIndexFieldNotGeopoint, geoIndexUnused, globalTableNearColumnLimit, gradeFromScore, hardcodedSecret, helperRole, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, isReachableSite, kvUnscopedUserKeyIdor, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, mutatorWithoutOwnerScope, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, notifyMissingPushConfig, notifySendOutsideAction, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, parseAdvisorMap, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, procedureWithoutStructuredEvent, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, readCallSiteCallers, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, scoreAdvisor, selfRescheduleWithoutProgress, shapeTargetsGlobalTable, shapeUnknownTable, signupMutationWithoutDisposableGating, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, throughRelationMissingUniqueIndex, topicTooManySubscriptions, ttlFieldNotTimestamp, unboundedCollectOnOpenRange, unboundedLoop, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, unrestrictedWhereBranch, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
package/dist/index.d.ts CHANGED
@@ -1605,14 +1605,30 @@ interface AdvisorExternalSource {
1605
1605
  * the holding table; for `many` it lives on the target. `name` is the accessor
1606
1606
  * the relation is loaded under.
1607
1607
  */
1608
- interface AdvisorRelation {
1608
+ interface AdvisorKeyedRelation {
1609
1609
  field: string;
1610
1610
  kind: "many" | "one";
1611
1611
  name: string;
1612
1612
  onDelete?: "cascade" | "restrict" | "set null";
1613
1613
  references: string;
1614
1614
  table: string;
1615
+ through?: never;
1615
1616
  }
1617
+ /**
1618
+ * A many-to-many relation (`r.many(target, { through })`): the link lives in the `through.table` join table,
1619
+ * whose `from` column points at the declaring table and `to` at `table`. It has no `field` of its own.
1620
+ */
1621
+ interface AdvisorThroughRelation {
1622
+ kind: "many";
1623
+ name: string;
1624
+ table: string;
1625
+ through: {
1626
+ from: string;
1627
+ table: string;
1628
+ to: string;
1629
+ };
1630
+ }
1631
+ type AdvisorRelation = AdvisorKeyedRelation | AdvisorThroughRelation;
1616
1632
  /**
1617
1633
  * Adapt the runtime `@lunora/server` {@link Schema} into an {@link AdvisorSchema}.
1618
1634
  * Runtime callers (the studio backend, a live shard) hold the real schema
@@ -4569,6 +4585,17 @@ declare const storageUploadWithoutMaxSize: Lint;
4569
4585
  * a runtime caller with no insert signal flags nothing rather than every table.
4570
4586
  */
4571
4587
  declare const tableWithoutInsert: Lint;
4588
+ /**
4589
+ * A correctness lint for many-to-many relations: the join table behind
4590
+ * `r.many(target, { through: { table, from, to } })` must carry a unique index over
4591
+ * exactly `(from, to)`.
4592
+ *
4593
+ * Without it a link is not a single row: a repeated `connect` stores the same pair
4594
+ * twice, and every read through the relation then returns the target twice. The
4595
+ * index is also what makes `set` a diff rather than a rewrite. `defineSchema` throws
4596
+ * on the same condition at load; this reports it at codegen time, before the app runs.
4597
+ */
4598
+ declare const throughRelationMissingUniqueIndex: Lint;
4572
4599
  /**
4573
4600
  * Flags a topic with more than {@link MAX_SUBSCRIPTIONS} subscriptions.
4574
4601
  *
@@ -5109,4 +5136,4 @@ interface RunAdvisorOptions {
5109
5136
  * `static` lints at build time and defer `runtime` lints to a live shard.
5110
5137
  */
5111
5138
  declare const runAdvisor: (context: LintContext, options?: RunAdvisorOptions) => Finding[];
5112
- export { ALL_LINTS, type AdvisorAdminRoute, type AdvisorAiRawRun, type AdvisorAiToolSideEffect, type AdvisorArgumentDerivedFetch, type AdvisorArgumentValidator, type AdvisorAuthApiCall, type AdvisorAuthConfig, type AdvisorBrowserUrlAccess, type AdvisorCallEdge, type AdvisorCallSiteScope, type AdvisorConfigCall, type AdvisorContainer, type AdvisorContainerKeyAccess, type AdvisorContainerOverride, type AdvisorExportSink, type AdvisorFailOpenGuard, type AdvisorFlagRead, type AdvisorFlagSecurityDefault, 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 AdvisorModule, type AdvisorMutatorDeclaration, 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 AdvisorRowEffect, type AdvisorSchema, type AdvisorSecretLiteral, type AdvisorShape, type AdvisorShardTraffic, type AdvisorSoftDeleteRead, type AdvisorSqlInterpolation, type AdvisorStaleMigrationImport, type AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableScan, type AdvisorTableWrite, type AdvisorUnboundedLoop, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type BaselineComparison, type CallSiteMetadata, 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, callSiteCallers, callSiteDescription, callSiteLabel, callSiteMetadata, circularFk, classifySensitivity, commitOrderedHardDelete, compareToBaseline, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, crossModuleTableWrite, dedupeCacheKeys, dispatchCycle, duplicateIndex, emptyIndex, errorWithoutCatalog, exportSinkMisconfigured, externalSourceIncrementalNoDeletePath, externalSourceOnGlobal, externalSourceUnscoped, fanOutBreadth, filterAfterIndexScan, filterOnPrimaryKey, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, flagReadInSubscription, fromServerSchema, geoIndexFieldNotGeopoint, geoIndexUnused, globalTableNearColumnLimit, gradeFromScore, hardcodedSecret, helperRole, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, isReachableSite, kvUnscopedUserKeyIdor, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, mutatorWithoutOwnerScope, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, notifyMissingPushConfig, notifySendOutsideAction, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, parseAdvisorMap, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, procedureWithoutStructuredEvent, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, readCallSiteCallers, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, scoreAdvisor, selfRescheduleWithoutProgress, shapeTargetsGlobalTable, shapeUnknownTable, signupMutationWithoutDisposableGating, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, topicTooManySubscriptions, ttlFieldNotTimestamp, unboundedCollectOnOpenRange, unboundedLoop, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, unrestrictedWhereBranch, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
5139
+ export { ALL_LINTS, type AdvisorAdminRoute, type AdvisorAiRawRun, type AdvisorAiToolSideEffect, type AdvisorArgumentDerivedFetch, type AdvisorArgumentValidator, type AdvisorAuthApiCall, type AdvisorAuthConfig, type AdvisorBrowserUrlAccess, type AdvisorCallEdge, type AdvisorCallSiteScope, type AdvisorConfigCall, type AdvisorContainer, type AdvisorContainerKeyAccess, type AdvisorContainerOverride, type AdvisorExportSink, type AdvisorFailOpenGuard, type AdvisorFlagRead, type AdvisorFlagSecurityDefault, type AdvisorGeoIndexUsage, type AdvisorHttpActionGuard, type AdvisorHttpHeaderWrite, type AdvisorHyperdriveCall, type AdvisorIdentityClaimRead, type AdvisorImageDeliveryUrlAccess, type AdvisorIndex, type AdvisorIndexHit, type AdvisorInsertWrite, type AdvisorKeyedRelation, type AdvisorKvKeyAccess, type AdvisorMailRecipientAccess, type AdvisorMap, type AdvisorMaskProcedure, type AdvisorMaskStrategy, type AdvisorModule, type AdvisorMutatorDeclaration, 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 AdvisorRowEffect, type AdvisorSchema, type AdvisorSecretLiteral, type AdvisorShape, type AdvisorShardTraffic, type AdvisorSoftDeleteRead, type AdvisorSqlInterpolation, type AdvisorStaleMigrationImport, type AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableScan, type AdvisorTableWrite, type AdvisorThroughRelation, type AdvisorUnboundedLoop, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type BaselineComparison, type CallSiteMetadata, 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, callSiteCallers, callSiteDescription, callSiteLabel, callSiteMetadata, circularFk, classifySensitivity, commitOrderedHardDelete, compareToBaseline, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, crossModuleTableWrite, dedupeCacheKeys, dispatchCycle, duplicateIndex, emptyIndex, errorWithoutCatalog, exportSinkMisconfigured, externalSourceIncrementalNoDeletePath, externalSourceOnGlobal, externalSourceUnscoped, fanOutBreadth, filterAfterIndexScan, filterOnPrimaryKey, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, flagReadInSubscription, fromServerSchema, geoIndexFieldNotGeopoint, geoIndexUnused, globalTableNearColumnLimit, gradeFromScore, hardcodedSecret, helperRole, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, isReachableSite, kvUnscopedUserKeyIdor, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, mutatorWithoutOwnerScope, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, notifyMissingPushConfig, notifySendOutsideAction, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, parseAdvisorMap, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, procedureWithoutStructuredEvent, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, readCallSiteCallers, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, scoreAdvisor, selfRescheduleWithoutProgress, shapeTargetsGlobalTable, shapeUnknownTable, signupMutationWithoutDisposableGating, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, throughRelationMissingUniqueIndex, topicTooManySubscriptions, ttlFieldNotTimestamp, unboundedCollectOnOpenRange, unboundedLoop, 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/fanOutBreadth-CBtmZnoh.mjs";import u from"./packem_shared/hotShard-BwGYZ3Tq.mjs";import h from"./packem_shared/indexUtilization-CkVPZcVe.mjs";import g from"./packem_shared/actionFetchSsrf-BK-kvOPO.mjs";import b from"./packem_shared/actionWithoutErrorHandling-4GCBT0_z.mjs";import y from"./packem_shared/adminRouteWithoutGuard-DPE7LuNh.mjs";import S from"./packem_shared/aiRawRunEscapeHatch-BW7a8kZC.mjs";import w from"./packem_shared/aiRunWithoutLogging-CvHHtEN9.mjs";import v from"./packem_shared/aiToolSideEffectPromptInjection-9eJXRlKt.mjs";import A from"./packem_shared/aiUnboundedGenerationPublic-C17h6sMV.mjs";import R from"./packem_shared/allowUnauthenticatedShardAccessEnabled-BQufF5Kb.mjs";import U from"./packem_shared/authApiCallWithoutHeaders-CReJRsGW.mjs";import W from"./packem_shared/authCsrfCheckDisabled-CRIVsvb9.mjs";import T from"./packem_shared/authEmailVerificationDisabled-BjFlnHr2.mjs";import I from"./packem_shared/authScimWithoutTransactions-B5ATiz5A.mjs";import C from"./packem_shared/authSecureCookiesDisabled-By8PVum3.mjs";import k from"./packem_shared/authSessionFreshageZero-DuxX3Ln9.mjs";import x from"./packem_shared/authTrustedOriginsWildcard-BKIh6788.mjs";import N from"./packem_shared/browserAllowPrivateTargets-Cj5sizhv.mjs";import F from"./packem_shared/browserUserUrlWithoutAllowlist-CzDEraJB.mjs";import O from"./packem_shared/circularFk-DtcWFJxK.mjs";import M from"./packem_shared/commitOrderedHardDelete-BPdwOKA7.mjs";import D from"./packem_shared/containerInstanceKeyFromUserInput-Bl-tAzKV.mjs";import P from"./packem_shared/containerOversizedInstance-Bx89uR7E.mjs";import $ from"./packem_shared/containerPublicInternet-BFfZf_P4.mjs";import E from"./packem_shared/containerRuntimeEgressRelaxation-4tMrhq1k.mjs";import K from"./packem_shared/containerStartEnableInternetOverride-mN_kuRtk.mjs";import L from"./packem_shared/crossModuleTableWrite-DjiVTAwK.mjs";import q from"./packem_shared/dispatchCycle-CWc5Q0cd.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 j from"./packem_shared/externalSourceOnGlobal-CH7xbJ49.mjs";import V from"./packem_shared/externalSourceUnscoped-BxU2uSXk.mjs";import Q from"./packem_shared/filterAfterIndexScan-CV8aPq7v.mjs";import X from"./packem_shared/filterOnPrimaryKey-BeHVg4w3.mjs";import Z from"./packem_shared/filterWithoutIndex-BGv3jbgg.mjs";import J from"./packem_shared/flagGatesSecurityWithUnsafeDefault-B5FBDF8c.mjs";import Y from"./packem_shared/flagReadInSubscription-DabIhYGD.mjs";import oo from"./packem_shared/geoIndexFieldNotGeopoint-BMQuok2-.mjs";import eo from"./packem_shared/geoIndexUnused-D7C9Qr4U.mjs";import ro from"./packem_shared/globalTableNearColumnLimit-BFbBBd6A.mjs";import to from"./packem_shared/hardcodedSecret-Bw_4FYrs.mjs";import io from"./packem_shared/httpActionMissingAuthGuard-DhMIs1EI.mjs";import no from"./packem_shared/httpActionResponseHeaderInjection-mcRYd3Zw.mjs";import ao from"./packem_shared/hyperdriveOutsideAction-CPDdGP2g.mjs";import mo from"./packem_shared/identityUndeclaredClaimTrusted-D1sEd5lr.mjs";import lo from"./packem_shared/imagesUrlSourceFromUserInput-BJXotuyO.mjs";import so from"./packem_shared/indexReferencesUnknownField-DKz4-bla.mjs";import po from"./packem_shared/insertManyUnsafeUserData-DWE8d_DF.mjs";import fo from"./packem_shared/kvUnscopedUserKeyIdor-DhymglIq.mjs";import co from"./packem_shared/mailInboundDispatchWithoutVerify-CWwqXyPX.mjs";import uo from"./packem_shared/mailRecipientFromRequestInput-BVXsZ4Xf.mjs";import ho from"./packem_shared/maskUncoveredPiiColumn-axEka4nd.mjs";import go from"./packem_shared/maskWeakHashStrategyOnPii-DJasagzX.mjs";import bo from"./packem_shared/maskedRelationLeakViaWith-CIFij6vE.mjs";import{e as a}from"./packem_shared/finding-NrKO8idM.mjs";import yo from"./packem_shared/mutatorFullRowReplace-BzRpZ47r.mjs";import So from"./packem_shared/mutatorWithoutOwnerScope-BoS81ns0.mjs";import wo from"./packem_shared/nondeterministicQueryMutation-Bbb-AGOS.mjs";import vo from"./packem_shared/normalizeIdUsedAsAuthorization-BXN-Can6.mjs";import Ao from"./packem_shared/notifyMissingPushConfig-DeQMoNwm.mjs";import Ro from"./packem_shared/notifySendOutsideAction-BJrDkr4h.mjs";import Uo from"./packem_shared/outputProjectionMissingOnPublicRead-DWSeo7oC.mjs";import Wo from"./packem_shared/ownerFieldFromArgsNotAuth-J8Xbz5uI.mjs";import To from"./packem_shared/paymentCreateWithoutAuthorize-CdenWpXD.mjs";import Io from"./packem_shared/paymentWebhookWideTolerance-DVhJB0Ip.mjs";import Co from"./packem_shared/plaintextSecretInWranglerVariables-bNkqmNqV.mjs";import ko from"./packem_shared/policyReferencesUnknownTable-CIKuRZ5Y.mjs";import xo from"./packem_shared/privilegedDispatchUnvalidatedPayload-BM3NtT57.mjs";import No from"./packem_shared/privilegedFanoutFromPublicProcedure-DV188gHQ.mjs";import Fo from"./packem_shared/procedureWithoutStructuredEvent-CZ_B23nM.mjs";import Oo from"./packem_shared/publicArgumentUsesAny-BDEvMA8Q.mjs";import Mo from"./packem_shared/publicMutationWithoutRatelimit-Bd-rRxnz.mjs";import Do from"./packem_shared/publicTableRlsOptoutConfusion-CbNk75Xo.mjs";import Po from"./packem_shared/queueWithoutDlq-BvHz3Opg.mjs";import $o from"./packem_shared/r2sqlOutsideAction-BdLiLOAX.mjs";import Eo from"./packem_shared/ratelimitDefaultMemoryStore-Dj0Kk7t9.mjs";import Ko from"./packem_shared/ratelimitKeySpoofableOrGlobal-DHMl74hR.mjs";import Lo from"./packem_shared/ratelimitMiddlewareFailOpen-Di2t8pDc.mjs";import qo from"./packem_shared/relationReferencesUnknownField-CJHOCSzs.mjs";import Go from"./packem_shared/relationReferencesUnknownTable-CP4aWtAJ.mjs";import _o from"./packem_shared/rlsUncoveredTable-CZ4ie4gX.mjs";import zo from"./packem_shared/selfRescheduleWithoutProgress-Be9d1bQ0.mjs";import Ho from"./packem_shared/shapeTargetsGlobalTable-Bu3eEDic.mjs";import Bo from"./packem_shared/shapeUnknownTable-CREfNnWi.mjs";import jo from"./packem_shared/signupMutationWithoutDisposableGating-BdKwtxDP.mjs";import Vo from"./packem_shared/softDeleteIncludeDeletedFromArgs-C7Ugg4zb.mjs";import Qo from"./packem_shared/sqlInjectionRisk-BYRllgPV.mjs";import Xo from"./packem_shared/storageGenerateUploadUrlNoContentTypePin-CrwFuo83.mjs";import Zo from"./packem_shared/storageKeyFromUserArgs-3vkxmI3v.mjs";import Jo from"./packem_shared/storagePresignedUrlForPrivateContent-C3KeV5tV.mjs";import Yo from"./packem_shared/storageUploadWithoutContentTypeAllowlist-BXoK_QWE.mjs";import oe from"./packem_shared/storageUploadWithoutMaxSize-CW7uKvSi.mjs";import ee from"./packem_shared/tableWithoutInsert-ClJp_jDr.mjs";import re from"./packem_shared/topicTooManySubscriptions-CiZhFm9r.mjs";import te from"./packem_shared/ttlFieldNotTimestamp-lnb5nmM6.mjs";import{s as ie,q as ne,c as ae}from"./packem_shared/helpers-DdZ_pyR3.mjs";import me from"./packem_shared/unboundedCollectOnOpenRange-DHy2RUL7.mjs";import le from"./packem_shared/unboundedLoop-DxN3_apu.mjs";import se from"./packem_shared/unboundedStringArgument-jZnCbwB0.mjs";import pe from"./packem_shared/unindexedForeignKey-Dypgn8uH.mjs";import fe from"./packem_shared/unindexedRelationTarget-CSqRJWYZ.mjs";import ce from"./packem_shared/unrestrictedWhereBranch-CcIBmHik.mjs";import de from"./packem_shared/userCreatingMutationWithoutCaptcha-D4TZEpgz.mjs";import ue from"./packem_shared/vectorsNamespaceFromUserInput-BWvGjJzp.mjs";import he from"./packem_shared/workflowDuplicateStepName-B6eAJzwA.mjs";import ge from"./packem_shared/workflowUnknownTarget-DEKB5H0g.mjs";import be from"./packem_shared/workflowUnused-DHwwE-1P.mjs";import{callSiteCallers as Nt,callSiteDescription as Ft,callSiteLabel as Ot,callSiteMetadata as Mt,helperRole as Dt,isReachableSite as Pt,readCallSiteCallers as $t}from"./packem_shared/callSiteCallers-DArHfQSU.mjs";import{compareToBaseline as Kt,parseAdvisorMap as Lt}from"./packem_shared/compareToBaseline-CUG59IOy.mjs";import{gradeFromScore as Gt}from"./packem_shared/gradeFromScore-KSt58rj1.mjs";import{MAP_VERSION as zt,byCodepoint as Ht,scoreAdvisor as Bt}from"./packem_shared/MAP_VERSION-MQ5W2B6n.mjs";import{default as Vt}from"./packem_shared/classifySensitivity-JnjaTGYi.mjs";import{fromServerSchema as Xt}from"./packem_shared/fromServerSchema-fAymN8o2.mjs";const ye={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 \`${ye[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"},Se=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`}]]),we={level:"WARN",scope:r=>`it loads every row of "${r}"`},l={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=ie(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:s}=Se.get(t??"")??we,p=ne(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(l,{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 — ${s(e.table)}.${f}`,level:n,metadata:{...ae(e),shardKind:t??"unknown",table:e.table}}))}return o},source:"static",title:"Unbounded collect"},ve=[so,Go,qo,ge,he,Bo,B,j,V,_,ro,z,oo,eo,H,te,M,O,L,pe,fe,G,ee,be,Po,re,X,Z,Q,l,me,le,q,zo,Ho,yo,So,wo,ao,$o,U,ko,_o,ho,go,P,$,Mo,ce,de,jo,Oo,se,to,Qo,y,To,co,Eo,N,No,Fo,po,A,g,b,Wo,Zo,fo,D,S,w,ue,uo,F,xo,K,E,I,x,W,C,T,k,lo,Ko,Do,R,Yo,oe,Xo,Jo,io,no,Lo,J,Y,v,mo,Io,Vo,bo,Uo,vo,Ro,Ao,Co,m],Ae=[u,h,d],Re=[...ve,...Ae],Ct=(r,o={})=>{const i=o.lints??Re,e=[];for(const t of i)o.source!==void 0&&t.source!==o.source||e.push(...t.run(r));return c(e)};export{Re as ALL_LINTS,zt as MAP_VERSION,Ae as RUNTIME_LINTS,ve as STATIC_LINTS,g as actionFetchSsrf,b as actionWithoutErrorHandling,y as adminRouteWithoutGuard,S as aiRawRunEscapeHatch,w as aiRunWithoutLogging,v as aiToolSideEffectPromptInjection,A as aiUnboundedGenerationPublic,R as allowUnauthenticatedShardAccessEnabled,U as authApiCallWithoutHeaders,W as authCsrfCheckDisabled,T as authEmailVerificationDisabled,I as authScimWithoutTransactions,C as authSecureCookiesDisabled,k as authSessionFreshageZero,x as authTrustedOriginsWildcard,N as browserAllowPrivateTargets,F as browserUserUrlWithoutAllowlist,Ht as byCodepoint,Nt as callSiteCallers,Ft as callSiteDescription,Ot as callSiteLabel,Mt as callSiteMetadata,O as circularFk,Vt as classifySensitivity,M as commitOrderedHardDelete,Kt as compareToBaseline,D as containerInstanceKeyFromUserInput,P as containerOversizedInstance,$ as containerPublicInternet,E as containerRuntimeEgressRelaxation,K as containerStartEnableInternetOverride,L as crossModuleTableWrite,c as dedupeCacheKeys,q as dispatchCycle,G as duplicateIndex,_ as emptyIndex,z as errorWithoutCatalog,H as exportSinkMisconfigured,B as externalSourceIncrementalNoDeletePath,j as externalSourceOnGlobal,V as externalSourceUnscoped,d as fanOutBreadth,Q as filterAfterIndexScan,X as filterOnPrimaryKey,Z as filterWithoutIndex,J as flagGatesSecurityWithUnsafeDefault,Y as flagReadInSubscription,Xt as fromServerSchema,oo as geoIndexFieldNotGeopoint,eo as geoIndexUnused,ro as globalTableNearColumnLimit,Gt as gradeFromScore,to as hardcodedSecret,Dt as helperRole,u as hotShard,io as httpActionMissingAuthGuard,no as httpActionResponseHeaderInjection,ao as hyperdriveOutsideAction,mo as identityUndeclaredClaimTrusted,lo as imagesUrlSourceFromUserInput,so as indexReferencesUnknownField,h as indexUtilization,po as insertManyUnsafeUserData,Pt as isReachableSite,fo as kvUnscopedUserKeyIdor,co as mailInboundDispatchWithoutVerify,uo as mailRecipientFromRequestInput,ho as maskUncoveredPiiColumn,go as maskWeakHashStrategyOnPii,bo as maskedRelationLeakViaWith,yo as mutatorFullRowReplace,So as mutatorWithoutOwnerScope,wo as nondeterministicQueryMutation,vo as normalizeIdUsedAsAuthorization,Ao as notifyMissingPushConfig,Ro as notifySendOutsideAction,Uo as outputProjectionMissingOnPublicRead,Wo as ownerFieldFromArgsNotAuth,Lt as parseAdvisorMap,To as paymentCreateWithoutAuthorize,Io as paymentWebhookWideTolerance,Co as plaintextSecretInWranglerVariables,ko as policyReferencesUnknownTable,xo as privilegedDispatchUnvalidatedPayload,No as privilegedFanoutFromPublicProcedure,Fo as procedureWithoutStructuredEvent,Oo as publicArgumentUsesAny,Mo as publicMutationWithoutRatelimit,Do as publicTableRlsOptoutConfusion,Po as queueWithoutDlq,$o as r2sqlOutsideAction,Eo as ratelimitDefaultMemoryStore,Ko as ratelimitKeySpoofableOrGlobal,Lo as ratelimitMiddlewareFailOpen,$t as readCallSiteCallers,qo as relationReferencesUnknownField,Go as relationReferencesUnknownTable,_o as rlsUncoveredTable,Ct as runAdvisor,Bt as scoreAdvisor,zo as selfRescheduleWithoutProgress,Ho as shapeTargetsGlobalTable,Bo as shapeUnknownTable,jo as signupMutationWithoutDisposableGating,Vo as softDeleteIncludeDeletedFromArgs,Qo as sqlInjectionRisk,Xo as storageGenerateUploadUrlNoContentTypePin,Zo as storageKeyFromUserArgs,Jo as storagePresignedUrlForPrivateContent,Yo as storageUploadWithoutContentTypeAllowlist,oe as storageUploadWithoutMaxSize,ee as tableWithoutInsert,re as topicTooManySubscriptions,te as ttlFieldNotTimestamp,me as unboundedCollectOnOpenRange,le as unboundedLoop,se as unboundedStringArgument,pe as unindexedForeignKey,fe as unindexedRelationTarget,ce as unrestrictedWhereBranch,de as userCreatingMutationWithoutCaptcha,ue as vectorsNamespaceFromUserInput,he as workflowDuplicateStepName,ge as workflowUnknownTarget,be as workflowUnused};
1
+ import{dedupeCacheKeys as c}from"./packem_shared/dedupeCacheKeys-DtBOHffV.mjs";import d from"./packem_shared/fanOutBreadth-CBtmZnoh.mjs";import u from"./packem_shared/hotShard-BwGYZ3Tq.mjs";import h from"./packem_shared/indexUtilization-CkVPZcVe.mjs";import g from"./packem_shared/actionFetchSsrf-BK-kvOPO.mjs";import b from"./packem_shared/actionWithoutErrorHandling-4GCBT0_z.mjs";import y from"./packem_shared/adminRouteWithoutGuard-DPE7LuNh.mjs";import S from"./packem_shared/aiRawRunEscapeHatch-BW7a8kZC.mjs";import w from"./packem_shared/aiRunWithoutLogging-CvHHtEN9.mjs";import v from"./packem_shared/aiToolSideEffectPromptInjection-9eJXRlKt.mjs";import R from"./packem_shared/aiUnboundedGenerationPublic-C17h6sMV.mjs";import A from"./packem_shared/allowUnauthenticatedShardAccessEnabled-BQufF5Kb.mjs";import U from"./packem_shared/authApiCallWithoutHeaders-CReJRsGW.mjs";import W from"./packem_shared/authCsrfCheckDisabled-CRIVsvb9.mjs";import T from"./packem_shared/authEmailVerificationDisabled-BjFlnHr2.mjs";import I from"./packem_shared/authScimWithoutTransactions-B5ATiz5A.mjs";import x from"./packem_shared/authSecureCookiesDisabled-By8PVum3.mjs";import C from"./packem_shared/authSessionFreshageZero-DuxX3Ln9.mjs";import k from"./packem_shared/authTrustedOriginsWildcard-BKIh6788.mjs";import N from"./packem_shared/browserAllowPrivateTargets-Cj5sizhv.mjs";import F from"./packem_shared/browserUserUrlWithoutAllowlist-CzDEraJB.mjs";import M from"./packem_shared/circularFk-DtcWFJxK.mjs";import O from"./packem_shared/commitOrderedHardDelete-BPdwOKA7.mjs";import D from"./packem_shared/containerInstanceKeyFromUserInput-Bl-tAzKV.mjs";import P from"./packem_shared/containerOversizedInstance-Bx89uR7E.mjs";import $ from"./packem_shared/containerPublicInternet-BFfZf_P4.mjs";import E from"./packem_shared/containerRuntimeEgressRelaxation-4tMrhq1k.mjs";import q from"./packem_shared/containerStartEnableInternetOverride-mN_kuRtk.mjs";import K from"./packem_shared/crossModuleTableWrite-DjiVTAwK.mjs";import L from"./packem_shared/dispatchCycle-CWc5Q0cd.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 j from"./packem_shared/externalSourceOnGlobal-CH7xbJ49.mjs";import V from"./packem_shared/externalSourceUnscoped-BxU2uSXk.mjs";import Q from"./packem_shared/filterAfterIndexScan-CV8aPq7v.mjs";import X from"./packem_shared/filterOnPrimaryKey-BeHVg4w3.mjs";import Z from"./packem_shared/filterWithoutIndex-BGv3jbgg.mjs";import J from"./packem_shared/flagGatesSecurityWithUnsafeDefault-B5FBDF8c.mjs";import Y from"./packem_shared/flagReadInSubscription-DabIhYGD.mjs";import oo from"./packem_shared/geoIndexFieldNotGeopoint-BMQuok2-.mjs";import eo from"./packem_shared/geoIndexUnused-D7C9Qr4U.mjs";import ro from"./packem_shared/globalTableNearColumnLimit-BFbBBd6A.mjs";import to from"./packem_shared/hardcodedSecret-Bw_4FYrs.mjs";import io from"./packem_shared/httpActionMissingAuthGuard-DhMIs1EI.mjs";import no from"./packem_shared/httpActionResponseHeaderInjection-mcRYd3Zw.mjs";import ao from"./packem_shared/hyperdriveOutsideAction-CPDdGP2g.mjs";import mo from"./packem_shared/identityUndeclaredClaimTrusted-D1sEd5lr.mjs";import lo from"./packem_shared/imagesUrlSourceFromUserInput-BJXotuyO.mjs";import so from"./packem_shared/indexReferencesUnknownField-DKz4-bla.mjs";import po from"./packem_shared/insertManyUnsafeUserData-DWE8d_DF.mjs";import fo from"./packem_shared/kvUnscopedUserKeyIdor-DhymglIq.mjs";import co from"./packem_shared/mailInboundDispatchWithoutVerify-CWwqXyPX.mjs";import uo from"./packem_shared/mailRecipientFromRequestInput-BVXsZ4Xf.mjs";import ho from"./packem_shared/maskUncoveredPiiColumn-axEka4nd.mjs";import go from"./packem_shared/maskWeakHashStrategyOnPii-DJasagzX.mjs";import bo from"./packem_shared/maskedRelationLeakViaWith-CIFij6vE.mjs";import{e as a}from"./packem_shared/finding-NrKO8idM.mjs";import yo from"./packem_shared/mutatorFullRowReplace-BzRpZ47r.mjs";import So from"./packem_shared/mutatorWithoutOwnerScope-BoS81ns0.mjs";import wo from"./packem_shared/nondeterministicQueryMutation-Bbb-AGOS.mjs";import vo from"./packem_shared/normalizeIdUsedAsAuthorization-BXN-Can6.mjs";import Ro from"./packem_shared/notifyMissingPushConfig-DeQMoNwm.mjs";import Ao from"./packem_shared/notifySendOutsideAction-BJrDkr4h.mjs";import Uo from"./packem_shared/outputProjectionMissingOnPublicRead-DWSeo7oC.mjs";import Wo from"./packem_shared/ownerFieldFromArgsNotAuth-J8Xbz5uI.mjs";import To from"./packem_shared/paymentCreateWithoutAuthorize-CdenWpXD.mjs";import Io from"./packem_shared/paymentWebhookWideTolerance-DVhJB0Ip.mjs";import xo from"./packem_shared/plaintextSecretInWranglerVariables-bNkqmNqV.mjs";import Co from"./packem_shared/policyReferencesUnknownTable-CIKuRZ5Y.mjs";import ko from"./packem_shared/privilegedDispatchUnvalidatedPayload-BM3NtT57.mjs";import No from"./packem_shared/privilegedFanoutFromPublicProcedure-DV188gHQ.mjs";import Fo from"./packem_shared/procedureWithoutStructuredEvent-CZ_B23nM.mjs";import Mo from"./packem_shared/publicArgumentUsesAny-BDEvMA8Q.mjs";import Oo from"./packem_shared/publicMutationWithoutRatelimit-Bd-rRxnz.mjs";import Do from"./packem_shared/publicTableRlsOptoutConfusion-CbNk75Xo.mjs";import Po from"./packem_shared/queueWithoutDlq-BvHz3Opg.mjs";import $o from"./packem_shared/r2sqlOutsideAction-BdLiLOAX.mjs";import Eo from"./packem_shared/ratelimitDefaultMemoryStore-Dj0Kk7t9.mjs";import qo from"./packem_shared/ratelimitKeySpoofableOrGlobal-DHMl74hR.mjs";import Ko from"./packem_shared/ratelimitMiddlewareFailOpen-Di2t8pDc.mjs";import Lo from"./packem_shared/relationReferencesUnknownField-Cl6mik8w.mjs";import Go from"./packem_shared/relationReferencesUnknownTable-vYjirSxf.mjs";import _o from"./packem_shared/rlsUncoveredTable-CZ4ie4gX.mjs";import zo from"./packem_shared/selfRescheduleWithoutProgress-Be9d1bQ0.mjs";import Ho from"./packem_shared/shapeTargetsGlobalTable-Bu3eEDic.mjs";import Bo from"./packem_shared/shapeUnknownTable-CREfNnWi.mjs";import jo from"./packem_shared/signupMutationWithoutDisposableGating-BdKwtxDP.mjs";import Vo from"./packem_shared/softDeleteIncludeDeletedFromArgs-C7Ugg4zb.mjs";import Qo from"./packem_shared/sqlInjectionRisk-BYRllgPV.mjs";import Xo from"./packem_shared/storageGenerateUploadUrlNoContentTypePin-CrwFuo83.mjs";import Zo from"./packem_shared/storageKeyFromUserArgs-3vkxmI3v.mjs";import Jo from"./packem_shared/storagePresignedUrlForPrivateContent-C3KeV5tV.mjs";import Yo from"./packem_shared/storageUploadWithoutContentTypeAllowlist-BXoK_QWE.mjs";import oe from"./packem_shared/storageUploadWithoutMaxSize-CW7uKvSi.mjs";import ee from"./packem_shared/tableWithoutInsert-ClJp_jDr.mjs";import re from"./packem_shared/throughRelationMissingUniqueIndex-Cg5e3GkS.mjs";import te from"./packem_shared/topicTooManySubscriptions-CiZhFm9r.mjs";import ie from"./packem_shared/ttlFieldNotTimestamp-lnb5nmM6.mjs";import{s as ne,q as ae,c as me}from"./packem_shared/helpers-DdZ_pyR3.mjs";import le from"./packem_shared/unboundedCollectOnOpenRange-DHy2RUL7.mjs";import se from"./packem_shared/unboundedLoop-DxN3_apu.mjs";import pe from"./packem_shared/unboundedStringArgument-jZnCbwB0.mjs";import fe from"./packem_shared/unindexedForeignKey-Dypgn8uH.mjs";import ce from"./packem_shared/unindexedRelationTarget-Dj2_NOCm.mjs";import de from"./packem_shared/unrestrictedWhereBranch-CcIBmHik.mjs";import ue from"./packem_shared/userCreatingMutationWithoutCaptcha-D4TZEpgz.mjs";import he from"./packem_shared/vectorsNamespaceFromUserInput-BWvGjJzp.mjs";import ge from"./packem_shared/workflowDuplicateStepName-B6eAJzwA.mjs";import be from"./packem_shared/workflowUnknownTarget-DEKB5H0g.mjs";import ye from"./packem_shared/workflowUnused-DHwwE-1P.mjs";import{callSiteCallers as Mt,callSiteDescription as Ot,callSiteLabel as Dt,callSiteMetadata as Pt,helperRole as $t,isReachableSite as Et,readCallSiteCallers as qt}from"./packem_shared/callSiteCallers-DArHfQSU.mjs";import{compareToBaseline as Lt,parseAdvisorMap as Gt}from"./packem_shared/compareToBaseline-CUG59IOy.mjs";import{gradeFromScore as zt}from"./packem_shared/gradeFromScore-KSt58rj1.mjs";import{MAP_VERSION as Bt,byCodepoint as jt,scoreAdvisor as Vt}from"./packem_shared/MAP_VERSION-MQ5W2B6n.mjs";import{default as Xt}from"./packem_shared/classifySensitivity-JnjaTGYi.mjs";import{fromServerSchema as Jt}from"./packem_shared/fromServerSchema-KWJd4PLE.mjs";const Se={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 \`${Se[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"},we=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`}]]),ve={level:"WARN",scope:r=>`it loads every row of "${r}"`},l={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=ne(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:s}=we.get(t??"")??ve,p=ae(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(l,{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 — ${s(e.table)}.${f}`,level:n,metadata:{...me(e),shardKind:t??"unknown",table:e.table}}))}return o},source:"static",title:"Unbounded collect"},Re=[so,Go,Lo,be,ge,Bo,B,j,V,_,ro,z,oo,eo,H,ie,O,M,K,fe,ce,re,G,ee,ye,Po,te,X,Z,Q,l,le,se,L,zo,Ho,yo,So,wo,ao,$o,U,Co,_o,ho,go,P,$,Oo,de,ue,jo,Mo,pe,to,Qo,y,To,co,Eo,N,No,Fo,po,R,g,b,Wo,Zo,fo,D,S,w,he,uo,F,ko,q,E,I,k,W,x,T,C,lo,qo,Do,A,Yo,oe,Xo,Jo,io,no,Ko,J,Y,v,mo,Io,Vo,bo,Uo,vo,Ao,Ro,xo,m],Ae=[u,h,d],Ue=[...Re,...Ae],kt=(r,o={})=>{const i=o.lints??Ue,e=[];for(const t of i)o.source!==void 0&&t.source!==o.source||e.push(...t.run(r));return c(e)};export{Ue as ALL_LINTS,Bt as MAP_VERSION,Ae as RUNTIME_LINTS,Re as STATIC_LINTS,g as actionFetchSsrf,b as actionWithoutErrorHandling,y as adminRouteWithoutGuard,S as aiRawRunEscapeHatch,w as aiRunWithoutLogging,v as aiToolSideEffectPromptInjection,R as aiUnboundedGenerationPublic,A as allowUnauthenticatedShardAccessEnabled,U as authApiCallWithoutHeaders,W as authCsrfCheckDisabled,T as authEmailVerificationDisabled,I as authScimWithoutTransactions,x as authSecureCookiesDisabled,C as authSessionFreshageZero,k as authTrustedOriginsWildcard,N as browserAllowPrivateTargets,F as browserUserUrlWithoutAllowlist,jt as byCodepoint,Mt as callSiteCallers,Ot as callSiteDescription,Dt as callSiteLabel,Pt as callSiteMetadata,M as circularFk,Xt as classifySensitivity,O as commitOrderedHardDelete,Lt as compareToBaseline,D as containerInstanceKeyFromUserInput,P as containerOversizedInstance,$ as containerPublicInternet,E as containerRuntimeEgressRelaxation,q as containerStartEnableInternetOverride,K as crossModuleTableWrite,c as dedupeCacheKeys,L as dispatchCycle,G as duplicateIndex,_ as emptyIndex,z as errorWithoutCatalog,H as exportSinkMisconfigured,B as externalSourceIncrementalNoDeletePath,j as externalSourceOnGlobal,V as externalSourceUnscoped,d as fanOutBreadth,Q as filterAfterIndexScan,X as filterOnPrimaryKey,Z as filterWithoutIndex,J as flagGatesSecurityWithUnsafeDefault,Y as flagReadInSubscription,Jt as fromServerSchema,oo as geoIndexFieldNotGeopoint,eo as geoIndexUnused,ro as globalTableNearColumnLimit,zt as gradeFromScore,to as hardcodedSecret,$t as helperRole,u as hotShard,io as httpActionMissingAuthGuard,no as httpActionResponseHeaderInjection,ao as hyperdriveOutsideAction,mo as identityUndeclaredClaimTrusted,lo as imagesUrlSourceFromUserInput,so as indexReferencesUnknownField,h as indexUtilization,po as insertManyUnsafeUserData,Et as isReachableSite,fo as kvUnscopedUserKeyIdor,co as mailInboundDispatchWithoutVerify,uo as mailRecipientFromRequestInput,ho as maskUncoveredPiiColumn,go as maskWeakHashStrategyOnPii,bo as maskedRelationLeakViaWith,yo as mutatorFullRowReplace,So as mutatorWithoutOwnerScope,wo as nondeterministicQueryMutation,vo as normalizeIdUsedAsAuthorization,Ro as notifyMissingPushConfig,Ao as notifySendOutsideAction,Uo as outputProjectionMissingOnPublicRead,Wo as ownerFieldFromArgsNotAuth,Gt as parseAdvisorMap,To as paymentCreateWithoutAuthorize,Io as paymentWebhookWideTolerance,xo as plaintextSecretInWranglerVariables,Co as policyReferencesUnknownTable,ko as privilegedDispatchUnvalidatedPayload,No as privilegedFanoutFromPublicProcedure,Fo as procedureWithoutStructuredEvent,Mo as publicArgumentUsesAny,Oo as publicMutationWithoutRatelimit,Do as publicTableRlsOptoutConfusion,Po as queueWithoutDlq,$o as r2sqlOutsideAction,Eo as ratelimitDefaultMemoryStore,qo as ratelimitKeySpoofableOrGlobal,Ko as ratelimitMiddlewareFailOpen,qt as readCallSiteCallers,Lo as relationReferencesUnknownField,Go as relationReferencesUnknownTable,_o as rlsUncoveredTable,kt as runAdvisor,Vt as scoreAdvisor,zo as selfRescheduleWithoutProgress,Ho as shapeTargetsGlobalTable,Bo as shapeUnknownTable,jo as signupMutationWithoutDisposableGating,Vo as softDeleteIncludeDeletedFromArgs,Qo as sqlInjectionRisk,Xo as storageGenerateUploadUrlNoContentTypePin,Zo as storageKeyFromUserArgs,Jo as storagePresignedUrlForPrivateContent,Yo as storageUploadWithoutContentTypeAllowlist,oe as storageUploadWithoutMaxSize,ee as tableWithoutInsert,re as throughRelationMissingUniqueIndex,te as topicTooManySubscriptions,ie as ttlFieldNotTimestamp,le as unboundedCollectOnOpenRange,se as unboundedLoop,pe as unboundedStringArgument,fe as unindexedForeignKey,ce as unindexedRelationTarget,de as unrestrictedWhereBranch,ue as userCreatingMutationWithoutCaptcha,he as vectorsNamespaceFromUserInput,ge as workflowDuplicateStepName,be as workflowUnknownTarget,ye as workflowUnused};
@@ -1 +1 @@
1
- const a=i=>({rlsMode:i.rlsMode,tables:Object.entries(i.tables).map(([d,n])=>{const o=[...n.indexes.map(e=>({fields:e.fields,kind:"index",name:e.name,unique:e.unique})),...n.searchIndexes.map(e=>({fields:[e.field,...e.filterFields??[]],kind:"search",name:e.name})),...n.rankIndexes.map(e=>({fields:[...e.sortBy.map(r=>r.field),...e.partitionBy??[]],kind:"rank",name:e.name})),...n.vectorIndexes.map(e=>({fields:[e.field],kind:"vector",name:e.name})),...n.geoIndexes.map(e=>({fields:[e.field],kind:"geo",name:e.name}))],s={};for(const[e,r]of Object.entries(n.shape))if(r.kind==="optional"){const t=r._meta?.inner;s[e]=t?.kind??r.kind}else s[e]=r.kind;return{externallyManaged:n.isExternallyManaged??!1,externalSource:n.externalSource?{hasReconcile:n.externalSource.reconcileEveryMs!==void 0,hasSoftDelete:n.externalSource.softDeleteColumn!==void 0,hasTenantBy:n.externalSource.tenantBy!==void 0,mode:n.externalSource.mode}:void 0,columnKinds:s,commitOrdered:n.commitOrderedMode,fields:Object.keys(n.shape),indexes:o,isPublic:n.isPublic??!1,name:d,shardKind:n.shardMode.kind,softDelete:n.softDeleteMode,ttl:n.ttlPolicy,relations:Object.entries(n.relationMap).map(([e,r])=>({field:r.field,kind:r.kind,name:e,onDelete:r.onDelete,references:r.references,table:r.table}))}})});export{a as fromServerSchema};
1
+ const a=i=>({rlsMode:i.rlsMode,tables:Object.entries(i.tables).map(([s,n])=>{const o=[...n.indexes.map(e=>({fields:e.fields,kind:"index",name:e.name,unique:e.unique})),...n.searchIndexes.map(e=>({fields:[e.field,...e.filterFields??[]],kind:"search",name:e.name})),...n.rankIndexes.map(e=>({fields:[...e.sortBy.map(r=>r.field),...e.partitionBy??[]],kind:"rank",name:e.name})),...n.vectorIndexes.map(e=>({fields:[e.field],kind:"vector",name:e.name})),...n.geoIndexes.map(e=>({fields:[e.field],kind:"geo",name:e.name}))],d={};for(const[e,r]of Object.entries(n.shape))if(r.kind==="optional"){const t=r._meta?.inner;d[e]=t?.kind??r.kind}else d[e]=r.kind;return{externallyManaged:n.isExternallyManaged??!1,externalSource:n.externalSource?{hasReconcile:n.externalSource.reconcileEveryMs!==void 0,hasSoftDelete:n.externalSource.softDeleteColumn!==void 0,hasTenantBy:n.externalSource.tenantBy!==void 0,mode:n.externalSource.mode}:void 0,columnKinds:d,commitOrdered:n.commitOrderedMode,fields:Object.keys(n.shape),indexes:o,isPublic:n.isPublic??!1,name:s,shardKind:n.shardMode.kind,softDelete:n.softDeleteMode,ttl:n.ttlPolicy,relations:Object.entries(n.relationMap).map(([e,r])=>r.through!==void 0?{kind:"many",name:e,table:r.table,through:{...r.through}}:{field:r.field,kind:r.kind,name:e,onDelete:r.onDelete,references:r.references,table:r.table})}})});export{a as fromServerSchema};
@@ -0,0 +1 @@
1
+ import{e as m}from"./finding-NrKO8idM.mjs";import{t as d}from"./helpers-DdZ_pyR3.mjs";const u=(o,r,a,n)=>{if(n.through!==void 0){const c=o.get(n.through.table);return c===void 0?[]:[n.through.from,n.through.to].filter(f=>!r(c).has(f)).map(f=>({column:f,owner:c.name,side:"field"}))}const e=o.get(n.table);if(!e)return[];const s=n.kind==="one"?a:e,t=n.kind==="one"?e:a,i=[];return r(s).has(n.field)||i.push({column:n.field,owner:s.name,side:"field"}),r(t).has(n.references)||i.push({column:n.references,owner:t.name,side:"references"}),i},l={categories:["SCHEMA"],description:"A relation references a foreign-key or referenced column that is not declared on its table, so the join can never resolve.",facing:"INTERNAL",level:"ERROR",name:"relation_references_unknown_field",remediation:"Fix the `field` / `references` column name in the relation, or add the missing column.",run:o=>{const r=new Map(o.schema.tables.map(e=>[e.name,e])),a=new Map,n=e=>{let s=a.get(e);return s||(s=d(e),a.set(e,s)),s};return o.schema.tables.flatMap(e=>e.relations.flatMap(s=>u(r,n,e,s).map(t=>m(l,{cacheKey:`relation_references_unknown_field:${e.name}:${s.name}:${t.side}`,detail:`Relation "${s.name}" on table "${e.name}" uses ${t.side} "${t.column}", which is not declared on table "${t.owner}".`,metadata:{column:t.column,owner:t.owner,relation:s.name,side:t.side,table:e.name}}))))},source:"static",title:"Relation references unknown field"};export{l as default};
@@ -0,0 +1 @@
1
+ import{e as s}from"./finding-NrKO8idM.mjs";const l={categories:["SCHEMA"],description:"A relation targets a table that does not exist in the schema. The relation can never load — the target is a typo or a removed/renamed table.",facing:"INTERNAL",level:"ERROR",name:"relation_references_unknown_table",remediation:"Fix the target table name in the relation, or add the missing table to the schema.",run:n=>{const r=new Set(n.schema.tables.map(e=>e.name));return n.schema.tables.flatMap(e=>e.relations.flatMap(a=>[{name:a.table,role:""},...a.through===void 0?[]:[{name:a.through.table,role:":through"}]].filter(({name:t})=>!r.has(t)).map(({name:t,role:o})=>s(l,{cacheKey:`relation_references_unknown_table:${e.name}:${a.name}${o}`,detail:`Relation "${a.name}" on table "${e.name}" targets table "${t}", which does not exist in the schema.`,metadata:{relation:a.name,table:e.name,target:t}}))))},source:"static",title:"Relation references unknown table"};export{l as default};
@@ -0,0 +1 @@
1
+ import{e as d}from"./finding-NrKO8idM.mjs";const h=(t,s,n)=>t.some(e=>e.unique===!0&&e.fields.length===2&&e.fields.includes(s)&&e.fields.includes(n)),l={categories:["SCHEMA"],description:"A many-to-many relation's join table has no unique index over its two keys, so the same link can be stored twice and every read through the relation returns the target twice.",facing:"INTERNAL",level:"ERROR",name:"through_relation_missing_unique_index",remediation:'Add a unique index over the two keys on the join table, e.g. `.index("byPostTag", ["postId", "tagId"], { unique: true })`.',run:t=>{const s=new Map(t.schema.tables.map(n=>[n.name,n]));return t.schema.tables.flatMap(n=>n.relations.flatMap(e=>{if(e.through===void 0)return[];const{from:i,table:o,to:a}=e.through,r=s.get(o);return r===void 0?[]:h(r.indexes.filter(u=>u.kind==="index"),i,a)?[]:[d(l,{cacheKey:`through_relation_missing_unique_index:${n.name}:${e.name}`,detail:`Relation "${e.name}" on table "${n.name}" goes through "${o}", which has no unique index over ("${i}", "${a}"). A repeated connect stores the same link twice.`,metadata:{relation:e.name,suggestedIndex:{fields:[i,a],name:`by_${i}_${a}`,unique:!0},table:o}})]}))},source:"static",title:"Through relation missing unique index"};export{l as default};
@@ -0,0 +1 @@
1
+ import{e as o}from"./finding-NrKO8idM.mjs";import{s as m,P as l,l as r}from"./fk-index-DXYS17cc.mjs";const d=e=>e.through===void 0?[{column:e.field,references:e.references,table:e.table}]:[{column:e.through.from,references:"_id",table:e.through.table},{column:e.through.to,references:"_id",table:e.through.table}],c=(e,i)=>i===l||e.relations.some(n=>n.kind==="one"&&n.field===i)||r(e).has(i),u={categories:["PERFORMANCE"],description:"A `many` relation's foreign-key column on the target table has no index leading with it. Relation predicates (`some`/`none`/`every`) and `with:` child reads filter the target on that column, full-scanning it as rows accumulate.",facing:"EXTERNAL",level:"INFO",name:"unindexed_relation_target",remediation:'Add a secondary index on the target table leading with the FK column, e.g. `.index("byAuthorId", ["authorId"])`.',run:e=>{const i=new Map(e.schema.tables.map(n=>[n.name,n]));return e.schema.tables.flatMap(n=>n.relations.filter(s=>s.kind==="many").flatMap(s=>d(s).flatMap(a=>{const t=i.get(a.table);return t===void 0||c(t,a.column)?[]:[o(u,{cacheKey:`unindexed_relation_target:${t.name}:${a.column}`,detail:`Relation "${s.name}" on table "${n.name}" is a to-many over "${t.name}" via its column "${a.column}", which is not the leading column of any index on "${t.name}". Relation predicates (\`some\`/\`none\`/\`every\`) and \`with:\` reads of "${s.name}" full-scan "${t.name}".`,metadata:{fkColumn:a.column,references:{column:a.references,table:n.name},relation:s.name,suggestedIndex:{fields:[a.column],name:m(a.column)},table:t.name}})]})))},source:"static",title:"Unindexed relation target"};export{u as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/advisor",
3
- "version": "1.0.0-alpha.210",
3
+ "version": "1.0.0-alpha.211",
4
4
  "description": "Schema & query lints (splinter-style advisors) for Lunora, feeding the Studio Advisors view",
5
5
  "keywords": [
6
6
  "advisor",
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "@lunora/errors": ">=1.0.0-alpha.51 <2.0.0-0",
50
- "@lunora/server": "1.0.0-alpha.194"
50
+ "@lunora/server": "1.0.0-alpha.195"
51
51
  },
52
52
  "engines": {
53
53
  "node": "^22.15.0 || >=24.11.0"
@@ -1 +0,0 @@
1
- import{e as c}from"./finding-NrKO8idM.mjs";import{t as m}from"./helpers-DdZ_pyR3.mjs";const f=(o,i,t,a)=>{const e=o.get(a.table);if(!e)return[];const n=a.kind==="one"?t:e,s=a.kind==="one"?e:t,r=[];return i(n).has(a.field)||r.push({column:a.field,owner:n.name,side:"field"}),i(s).has(a.references)||r.push({column:a.references,owner:s.name,side:"references"}),r},d={categories:["SCHEMA"],description:"A relation references a foreign-key or referenced column that is not declared on its table, so the join can never resolve.",facing:"INTERNAL",level:"ERROR",name:"relation_references_unknown_field",remediation:"Fix the `field` / `references` column name in the relation, or add the missing column.",run:o=>{const i=new Map(o.schema.tables.map(e=>[e.name,e])),t=new Map,a=e=>{let n=t.get(e);return n||(n=m(e),t.set(e,n)),n};return o.schema.tables.flatMap(e=>e.relations.flatMap(n=>f(i,a,e,n).map(s=>c(d,{cacheKey:`relation_references_unknown_field:${e.name}:${n.name}:${s.side}`,detail:`Relation "${n.name}" on table "${e.name}" uses ${s.side} "${s.column}", which is not declared on table "${s.owner}".`,metadata:{column:s.column,owner:s.owner,relation:n.name,side:s.side,table:e.name}}))))},source:"static",title:"Relation references unknown field"};export{d as default};
@@ -1 +0,0 @@
1
- import{e as r}from"./finding-NrKO8idM.mjs";const s={categories:["SCHEMA"],description:"A relation targets a table that does not exist in the schema. The relation can never load — the target is a typo or a removed/renamed table.",facing:"INTERNAL",level:"ERROR",name:"relation_references_unknown_table",remediation:"Fix the target table name in the relation, or add the missing table to the schema.",run:t=>{const n=new Set(t.schema.tables.map(a=>a.name));return t.schema.tables.flatMap(a=>a.relations.filter(e=>!n.has(e.table)).map(e=>r(s,{cacheKey:`relation_references_unknown_table:${a.name}:${e.name}`,detail:`Relation "${e.name}" on table "${a.name}" targets table "${e.table}", which does not exist in the schema.`,metadata:{relation:e.name,table:a.name,target:e.table}})))},source:"static",title:"Relation references unknown table"};export{s as default};
@@ -1 +0,0 @@
1
- import{e as d}from"./finding-NrKO8idM.mjs";import{P as c,l as m,s as u}from"./fk-index-DXYS17cc.mjs";const g={categories:["PERFORMANCE"],description:"A `many` relation's foreign-key column on the target table has no index leading with it. Relation predicates (`some`/`none`/`every`) and `with:` child reads filter the target on that column, full-scanning it as rows accumulate.",facing:"EXTERNAL",level:"INFO",name:"unindexed_relation_target",remediation:'Add a secondary index on the target table leading with the FK column, e.g. `.index("byAuthorId", ["authorId"])`.',run:i=>{const o=[],l=new Map(i.schema.tables.map(t=>[t.name,t]));for(const t of i.schema.tables)for(const e of t.relations){if(e.kind!=="many")continue;const a=l.get(e.table);if(a===void 0)continue;const n=e.field;if(n===c||a.relations.some(s=>s.kind==="one"&&s.field===n)||m(a).has(n))continue;const r=u(n);o.push(d(g,{cacheKey:`unindexed_relation_target:${e.table}:${n}`,detail:`Relation "${e.name}" on table "${t.name}" is a to-many over "${e.table}" via its column "${n}", which is not the leading column of any index on "${e.table}". Relation predicates (\`some\`/\`none\`/\`every\`) and \`with:\` reads of "${e.name}" full-scan "${e.table}".`,metadata:{fkColumn:n,references:{column:e.references,table:t.name},relation:e.name,suggestedIndex:{fields:[n],name:r},table:e.table}}))}return o},source:"static",title:"Unindexed relation target"};export{g as default};