@lunora/advisor 1.0.0-alpha.28 → 1.0.0-alpha.29
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 +29 -3
- package/dist/index.d.ts +29 -3
- package/dist/index.mjs +4 -2
- package/dist/packem_shared/externalSourceIncrementalNoDeletePath-DvX9cRBD.mjs +45 -0
- package/dist/packem_shared/{fromServerSchema-S_5u6A_Y.mjs → fromServerSchema-BjAZdvJ6.mjs} +1 -4
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1085,11 +1085,13 @@ interface AdvisorIndex {
|
|
|
1085
1085
|
}
|
|
1086
1086
|
/** The statically-knowable `.source(...)` bits the `external_source_*` lints read. */
|
|
1087
1087
|
interface AdvisorExternalSource {
|
|
1088
|
-
/** `true` when a `reconcileEveryMs` was given —
|
|
1088
|
+
/** `true` when a `reconcileEveryMs` was given — one incremental delete-visibility path the `external_source_incremental_no_delete_path` lint accepts. */
|
|
1089
1089
|
hasReconcile?: boolean;
|
|
1090
|
+
/** `true` when a `softDeleteColumn` was given — the other incremental delete-visibility path. */
|
|
1091
|
+
hasSoftDelete?: boolean;
|
|
1090
1092
|
/** `true` when a `tenantBy` mapper was given — the tenant-isolation boundary. */
|
|
1091
1093
|
hasTenantBy: boolean;
|
|
1092
|
-
/** Delete-detection mode literal, when given (`"full-pull"`
|
|
1094
|
+
/** Delete-detection mode literal, when given (`"full-pull"` or `"incremental"`). */
|
|
1093
1095
|
mode?: string;
|
|
1094
1096
|
/**
|
|
1095
1097
|
* `true` when `.source(...)` was declared but its config wasn't a static object
|
|
@@ -2468,6 +2470,30 @@ declare const duplicateIndex: Lint;
|
|
|
2468
2470
|
*/
|
|
2469
2471
|
declare const emptyIndex: Lint;
|
|
2470
2472
|
/**
|
|
2473
|
+
* Flags a `.source({ mode: "incremental" })` table that declares neither a
|
|
2474
|
+
* `reconcileEveryMs` sweep nor a `softDeleteColumn` (plan 136).
|
|
2475
|
+
*
|
|
2476
|
+
* Incremental ingest pulls only rows past a watermark, so an upstream **delete**
|
|
2477
|
+
* is invisible to it — the deleted row simply stops appearing in the changed-rows
|
|
2478
|
+
* slice, and the locally-materialized copy lingers forever. Over time the table
|
|
2479
|
+
* fills with phantom rows that no longer exist upstream, which `defineShape` then
|
|
2480
|
+
* serves to clients as live data. That is silent data corruption, so it is an
|
|
2481
|
+
* `ERROR` (STOP) that fails the build.
|
|
2482
|
+
*
|
|
2483
|
+
* The fix is a declared delete-visibility path: `reconcileEveryMs` (a periodic
|
|
2484
|
+
* full-pull sweep that GCs vanished rows) or `softDeleteColumn` (an upstream
|
|
2485
|
+
* tombstone column the incremental pull returns, turned into a local delete).
|
|
2486
|
+
*
|
|
2487
|
+
* `defineSchema` throws on this exact condition too — this lint is the build-time
|
|
2488
|
+
* mirror (same belt-and-suspenders as `external_source_unscoped`), and it also
|
|
2489
|
+
* covers the `unanalyzable` config case the runtime guard can't see.
|
|
2490
|
+
*
|
|
2491
|
+
* **Evidence supply**: reads `table.externalSource.{mode,hasReconcile,hasSoftDelete}`
|
|
2492
|
+
* (the codegen feeder captures them from `.source({...})`; the runtime feeder
|
|
2493
|
+
* derives them). A non-incremental source, or one with either delete path, is skipped.
|
|
2494
|
+
*/
|
|
2495
|
+
declare const externalSourceIncrementalNoDeletePath: Lint;
|
|
2496
|
+
/**
|
|
2471
2497
|
* Flags a table that is both `.source(...)` and `.global()`.
|
|
2472
2498
|
*
|
|
2473
2499
|
* The two are contradictory. `.global()` already places a table in an external
|
|
@@ -3627,4 +3653,4 @@ interface RunAdvisorOptions {
|
|
|
3627
3653
|
* `static` lints at build time and defer `runtime` lints to a live shard.
|
|
3628
3654
|
*/
|
|
3629
3655
|
declare const runAdvisor: (context: LintContext, options?: RunAdvisorOptions) => Finding[];
|
|
3630
|
-
export { AE_METRIC_EVENTS, 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 AdvisorFailOpenGuard, type AdvisorFlagSecurityDefault, type AdvisorHttpActionGuard, type AdvisorHttpHeaderWrite, type AdvisorHyperdriveCall, type AdvisorIdentityClaimRead, type AdvisorImageDeliveryUrlAccess, type AdvisorIndex, type AdvisorIndexHit, type AdvisorInsertWrite, type AdvisorKvKeyAccess, type AdvisorMailRecipientAccess, type AdvisorMaskProcedure, type AdvisorMaskStrategy, type AdvisorMutatorWrite, type AdvisorNondeterministicCall, type AdvisorNormalizeIdAuthorization, 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 AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableSample, type AdvisorTableScan, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type Category, type Facing, type Finding, type Level, type Lint, type LintContext, type LintSource, RUNTIME_LINTS, RunAdvisorOptions, STATIC_LINTS, actionFetchSsrf, adminRouteWithoutGuard, aiRawRunEscapeHatch, aiToolSideEffectPromptInjection, aiUnboundedGenerationPublic, allowUnauthenticatedShardAccessEnabled, authApiCallWithoutHeaders, authCsrfCheckDisabled, authEmailVerificationDisabled, authSecureCookiesDisabled, authSessionFreshageZero, authTrustedOriginsWildcard, browserAllowPrivateTargets, browserUserUrlWithoutAllowlist, circularFk, constraintValidator, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, dedupeCacheKeys, duplicateIndex, emptyIndex, externalSourceOnGlobal, externalSourceUnscoped, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, fromServerSchema, hardcodedSecret, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, kvUnscopedUserKeyIdor, loadAnalyticsRuntimeMetrics, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, shapeTargetsGlobalTable, shapeUnknownTable, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
|
|
3656
|
+
export { AE_METRIC_EVENTS, 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 AdvisorFailOpenGuard, type AdvisorFlagSecurityDefault, type AdvisorHttpActionGuard, type AdvisorHttpHeaderWrite, type AdvisorHyperdriveCall, type AdvisorIdentityClaimRead, type AdvisorImageDeliveryUrlAccess, type AdvisorIndex, type AdvisorIndexHit, type AdvisorInsertWrite, type AdvisorKvKeyAccess, type AdvisorMailRecipientAccess, type AdvisorMaskProcedure, type AdvisorMaskStrategy, type AdvisorMutatorWrite, type AdvisorNondeterministicCall, type AdvisorNormalizeIdAuthorization, 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 AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableSample, type AdvisorTableScan, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type Category, type Facing, type Finding, type Level, type Lint, type LintContext, type LintSource, RUNTIME_LINTS, RunAdvisorOptions, STATIC_LINTS, actionFetchSsrf, adminRouteWithoutGuard, aiRawRunEscapeHatch, aiToolSideEffectPromptInjection, aiUnboundedGenerationPublic, allowUnauthenticatedShardAccessEnabled, authApiCallWithoutHeaders, authCsrfCheckDisabled, authEmailVerificationDisabled, authSecureCookiesDisabled, authSessionFreshageZero, authTrustedOriginsWildcard, browserAllowPrivateTargets, browserUserUrlWithoutAllowlist, circularFk, constraintValidator, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, dedupeCacheKeys, duplicateIndex, emptyIndex, externalSourceIncrementalNoDeletePath, externalSourceOnGlobal, externalSourceUnscoped, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, fromServerSchema, hardcodedSecret, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, kvUnscopedUserKeyIdor, loadAnalyticsRuntimeMetrics, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, shapeTargetsGlobalTable, shapeUnknownTable, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
|
package/dist/index.d.ts
CHANGED
|
@@ -1085,11 +1085,13 @@ interface AdvisorIndex {
|
|
|
1085
1085
|
}
|
|
1086
1086
|
/** The statically-knowable `.source(...)` bits the `external_source_*` lints read. */
|
|
1087
1087
|
interface AdvisorExternalSource {
|
|
1088
|
-
/** `true` when a `reconcileEveryMs` was given —
|
|
1088
|
+
/** `true` when a `reconcileEveryMs` was given — one incremental delete-visibility path the `external_source_incremental_no_delete_path` lint accepts. */
|
|
1089
1089
|
hasReconcile?: boolean;
|
|
1090
|
+
/** `true` when a `softDeleteColumn` was given — the other incremental delete-visibility path. */
|
|
1091
|
+
hasSoftDelete?: boolean;
|
|
1090
1092
|
/** `true` when a `tenantBy` mapper was given — the tenant-isolation boundary. */
|
|
1091
1093
|
hasTenantBy: boolean;
|
|
1092
|
-
/** Delete-detection mode literal, when given (`"full-pull"`
|
|
1094
|
+
/** Delete-detection mode literal, when given (`"full-pull"` or `"incremental"`). */
|
|
1093
1095
|
mode?: string;
|
|
1094
1096
|
/**
|
|
1095
1097
|
* `true` when `.source(...)` was declared but its config wasn't a static object
|
|
@@ -2468,6 +2470,30 @@ declare const duplicateIndex: Lint;
|
|
|
2468
2470
|
*/
|
|
2469
2471
|
declare const emptyIndex: Lint;
|
|
2470
2472
|
/**
|
|
2473
|
+
* Flags a `.source({ mode: "incremental" })` table that declares neither a
|
|
2474
|
+
* `reconcileEveryMs` sweep nor a `softDeleteColumn` (plan 136).
|
|
2475
|
+
*
|
|
2476
|
+
* Incremental ingest pulls only rows past a watermark, so an upstream **delete**
|
|
2477
|
+
* is invisible to it — the deleted row simply stops appearing in the changed-rows
|
|
2478
|
+
* slice, and the locally-materialized copy lingers forever. Over time the table
|
|
2479
|
+
* fills with phantom rows that no longer exist upstream, which `defineShape` then
|
|
2480
|
+
* serves to clients as live data. That is silent data corruption, so it is an
|
|
2481
|
+
* `ERROR` (STOP) that fails the build.
|
|
2482
|
+
*
|
|
2483
|
+
* The fix is a declared delete-visibility path: `reconcileEveryMs` (a periodic
|
|
2484
|
+
* full-pull sweep that GCs vanished rows) or `softDeleteColumn` (an upstream
|
|
2485
|
+
* tombstone column the incremental pull returns, turned into a local delete).
|
|
2486
|
+
*
|
|
2487
|
+
* `defineSchema` throws on this exact condition too — this lint is the build-time
|
|
2488
|
+
* mirror (same belt-and-suspenders as `external_source_unscoped`), and it also
|
|
2489
|
+
* covers the `unanalyzable` config case the runtime guard can't see.
|
|
2490
|
+
*
|
|
2491
|
+
* **Evidence supply**: reads `table.externalSource.{mode,hasReconcile,hasSoftDelete}`
|
|
2492
|
+
* (the codegen feeder captures them from `.source({...})`; the runtime feeder
|
|
2493
|
+
* derives them). A non-incremental source, or one with either delete path, is skipped.
|
|
2494
|
+
*/
|
|
2495
|
+
declare const externalSourceIncrementalNoDeletePath: Lint;
|
|
2496
|
+
/**
|
|
2471
2497
|
* Flags a table that is both `.source(...)` and `.global()`.
|
|
2472
2498
|
*
|
|
2473
2499
|
* The two are contradictory. `.global()` already places a table in an external
|
|
@@ -3627,4 +3653,4 @@ interface RunAdvisorOptions {
|
|
|
3627
3653
|
* `static` lints at build time and defer `runtime` lints to a live shard.
|
|
3628
3654
|
*/
|
|
3629
3655
|
declare const runAdvisor: (context: LintContext, options?: RunAdvisorOptions) => Finding[];
|
|
3630
|
-
export { AE_METRIC_EVENTS, 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 AdvisorFailOpenGuard, type AdvisorFlagSecurityDefault, type AdvisorHttpActionGuard, type AdvisorHttpHeaderWrite, type AdvisorHyperdriveCall, type AdvisorIdentityClaimRead, type AdvisorImageDeliveryUrlAccess, type AdvisorIndex, type AdvisorIndexHit, type AdvisorInsertWrite, type AdvisorKvKeyAccess, type AdvisorMailRecipientAccess, type AdvisorMaskProcedure, type AdvisorMaskStrategy, type AdvisorMutatorWrite, type AdvisorNondeterministicCall, type AdvisorNormalizeIdAuthorization, 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 AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableSample, type AdvisorTableScan, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type Category, type Facing, type Finding, type Level, type Lint, type LintContext, type LintSource, RUNTIME_LINTS, RunAdvisorOptions, STATIC_LINTS, actionFetchSsrf, adminRouteWithoutGuard, aiRawRunEscapeHatch, aiToolSideEffectPromptInjection, aiUnboundedGenerationPublic, allowUnauthenticatedShardAccessEnabled, authApiCallWithoutHeaders, authCsrfCheckDisabled, authEmailVerificationDisabled, authSecureCookiesDisabled, authSessionFreshageZero, authTrustedOriginsWildcard, browserAllowPrivateTargets, browserUserUrlWithoutAllowlist, circularFk, constraintValidator, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, dedupeCacheKeys, duplicateIndex, emptyIndex, externalSourceOnGlobal, externalSourceUnscoped, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, fromServerSchema, hardcodedSecret, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, kvUnscopedUserKeyIdor, loadAnalyticsRuntimeMetrics, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, shapeTargetsGlobalTable, shapeUnknownTable, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
|
|
3656
|
+
export { AE_METRIC_EVENTS, 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 AdvisorFailOpenGuard, type AdvisorFlagSecurityDefault, type AdvisorHttpActionGuard, type AdvisorHttpHeaderWrite, type AdvisorHyperdriveCall, type AdvisorIdentityClaimRead, type AdvisorImageDeliveryUrlAccess, type AdvisorIndex, type AdvisorIndexHit, type AdvisorInsertWrite, type AdvisorKvKeyAccess, type AdvisorMailRecipientAccess, type AdvisorMaskProcedure, type AdvisorMaskStrategy, type AdvisorMutatorWrite, type AdvisorNondeterministicCall, type AdvisorNormalizeIdAuthorization, 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 AdvisorStorageKeyAccess, type AdvisorStorageUpload, type AdvisorTable, type AdvisorTableSample, type AdvisorTableScan, type AdvisorVectorNamespaceAccess, type AdvisorWorkflow, type AdvisorWorkflowCall, type AdvisorWranglerVariable, type AnalyticsMetricsOptions, type AnalyticsMetricsSource, type AnalyticsRuntimeMetrics, type Category, type Facing, type Finding, type Level, type Lint, type LintContext, type LintSource, RUNTIME_LINTS, RunAdvisorOptions, STATIC_LINTS, actionFetchSsrf, adminRouteWithoutGuard, aiRawRunEscapeHatch, aiToolSideEffectPromptInjection, aiUnboundedGenerationPublic, allowUnauthenticatedShardAccessEnabled, authApiCallWithoutHeaders, authCsrfCheckDisabled, authEmailVerificationDisabled, authSecureCookiesDisabled, authSessionFreshageZero, authTrustedOriginsWildcard, browserAllowPrivateTargets, browserUserUrlWithoutAllowlist, circularFk, constraintValidator, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, dedupeCacheKeys, duplicateIndex, emptyIndex, externalSourceIncrementalNoDeletePath, externalSourceOnGlobal, externalSourceUnscoped, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, fromServerSchema, hardcodedSecret, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, kvUnscopedUserKeyIdor, loadAnalyticsRuntimeMetrics, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, shapeTargetsGlobalTable, shapeUnknownTable, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
|
package/dist/index.mjs
CHANGED
|
@@ -24,6 +24,7 @@ import containerRuntimeEgressRelaxation from './packem_shared/containerRuntimeEg
|
|
|
24
24
|
import containerStartEnableInternetOverride from './packem_shared/containerStartEnableInternetOverride-DDaHZQ1L.mjs';
|
|
25
25
|
import duplicateIndex from './packem_shared/duplicateIndex-BOublMSt.mjs';
|
|
26
26
|
import emptyIndex from './packem_shared/emptyIndex-BX8EuEY7.mjs';
|
|
27
|
+
import externalSourceIncrementalNoDeletePath from './packem_shared/externalSourceIncrementalNoDeletePath-DvX9cRBD.mjs';
|
|
27
28
|
import externalSourceOnGlobal from './packem_shared/externalSourceOnGlobal-Bg-NfCX9.mjs';
|
|
28
29
|
import externalSourceUnscoped from './packem_shared/externalSourceUnscoped-5vT-Bup3.mjs';
|
|
29
30
|
import filterWithoutIndex from './packem_shared/filterWithoutIndex-BYVeJaSs.mjs';
|
|
@@ -83,7 +84,7 @@ import workflowDuplicateStepName from './packem_shared/workflowDuplicateStepName
|
|
|
83
84
|
import workflowUnknownTarget from './packem_shared/workflowUnknownTarget-Cdd7WhKQ.mjs';
|
|
84
85
|
import workflowUnused from './packem_shared/workflowUnused-D0jHxdz9.mjs';
|
|
85
86
|
export { AE_METRIC_EVENTS, loadAnalyticsRuntimeMetrics } from './packem_shared/AE_METRIC_EVENTS-BM14d0lm.mjs';
|
|
86
|
-
export { fromServerSchema } from './packem_shared/fromServerSchema-
|
|
87
|
+
export { fromServerSchema } from './packem_shared/fromServerSchema-BjAZdvJ6.mjs';
|
|
87
88
|
|
|
88
89
|
const STATIC_LINTS = [
|
|
89
90
|
indexReferencesUnknownField,
|
|
@@ -92,6 +93,7 @@ const STATIC_LINTS = [
|
|
|
92
93
|
workflowUnknownTarget,
|
|
93
94
|
workflowDuplicateStepName,
|
|
94
95
|
shapeUnknownTable,
|
|
96
|
+
externalSourceIncrementalNoDeletePath,
|
|
95
97
|
externalSourceOnGlobal,
|
|
96
98
|
externalSourceUnscoped,
|
|
97
99
|
emptyIndex,
|
|
@@ -181,4 +183,4 @@ const runAdvisor = (context, options = {}) => {
|
|
|
181
183
|
return dedupeCacheKeys(findings);
|
|
182
184
|
};
|
|
183
185
|
|
|
184
|
-
export { ALL_LINTS, RUNTIME_LINTS, STATIC_LINTS, actionFetchSsrf, adminRouteWithoutGuard, aiRawRunEscapeHatch, aiToolSideEffectPromptInjection, aiUnboundedGenerationPublic, allowUnauthenticatedShardAccessEnabled, authApiCallWithoutHeaders, authCsrfCheckDisabled, authEmailVerificationDisabled, authSecureCookiesDisabled, authSessionFreshageZero, authTrustedOriginsWildcard, browserAllowPrivateTargets, browserUserUrlWithoutAllowlist, circularFk, constraintValidator, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, dedupeCacheKeys, duplicateIndex, emptyIndex, externalSourceOnGlobal, externalSourceUnscoped, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, hardcodedSecret, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, kvUnscopedUserKeyIdor, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, shapeTargetsGlobalTable, shapeUnknownTable, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
|
|
186
|
+
export { ALL_LINTS, RUNTIME_LINTS, STATIC_LINTS, actionFetchSsrf, adminRouteWithoutGuard, aiRawRunEscapeHatch, aiToolSideEffectPromptInjection, aiUnboundedGenerationPublic, allowUnauthenticatedShardAccessEnabled, authApiCallWithoutHeaders, authCsrfCheckDisabled, authEmailVerificationDisabled, authSecureCookiesDisabled, authSessionFreshageZero, authTrustedOriginsWildcard, browserAllowPrivateTargets, browserUserUrlWithoutAllowlist, circularFk, constraintValidator, containerInstanceKeyFromUserInput, containerOversizedInstance, containerPublicInternet, containerRuntimeEgressRelaxation, containerStartEnableInternetOverride, dedupeCacheKeys, duplicateIndex, emptyIndex, externalSourceIncrementalNoDeletePath, externalSourceOnGlobal, externalSourceUnscoped, filterWithoutIndex, flagGatesSecurityWithUnsafeDefault, hardcodedSecret, hotShard, httpActionMissingAuthGuard, httpActionResponseHeaderInjection, hyperdriveOutsideAction, identityUndeclaredClaimTrusted, imagesUrlSourceFromUserInput, indexReferencesUnknownField, indexUtilization, insertManyUnsafeUserData, kvUnscopedUserKeyIdor, mailInboundDispatchWithoutVerify, mailRecipientFromRequestInput, maskUncoveredPiiColumn, maskWeakHashStrategyOnPii, maskedRelationLeakViaWith, mutatorFullRowReplace, nondeterministicQueryMutation, normalizeIdUsedAsAuthorization, outputProjectionMissingOnPublicRead, ownerFieldFromArgsNotAuth, paymentCreateWithoutAuthorize, paymentWebhookWideTolerance, plaintextSecretInWranglerVariables, policyReferencesUnknownTable, privilegedDispatchUnvalidatedPayload, privilegedFanoutFromPublicProcedure, publicArgumentUsesAny, publicMutationWithoutRatelimit, publicTableRlsOptoutConfusion, queueWithoutDlq, r2sqlOutsideAction, ratelimitDefaultMemoryStore, ratelimitKeySpoofableOrGlobal, ratelimitMiddlewareFailOpen, relationReferencesUnknownField, relationReferencesUnknownTable, rlsUncoveredTable, runAdvisor, shapeTargetsGlobalTable, shapeUnknownTable, softDeleteIncludeDeletedFromArgs, sqlInjectionRisk, storageGenerateUploadUrlNoContentTypePin, storageKeyFromUserArgs, storagePresignedUrlForPrivateContent, storageUploadWithoutContentTypeAllowlist, storageUploadWithoutMaxSize, tableWithoutInsert, unboundedStringArgument, unindexedForeignKey, unindexedRelationTarget, userCreatingMutationWithoutCaptcha, vectorsNamespaceFromUserInput, workflowDuplicateStepName, workflowUnknownTarget, workflowUnused };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { e as emit } from './finding-Dm_zvzS1.mjs';
|
|
2
|
+
|
|
3
|
+
const externalSourceIncrementalNoDeletePath = {
|
|
4
|
+
categories: ["SCHEMA"],
|
|
5
|
+
description: "A `.source({ mode: 'incremental' })` table declares no delete-visibility path (`reconcileEveryMs` or `softDeleteColumn`), so upstream deletes are never applied and the materialized table accumulates phantom rows.",
|
|
6
|
+
facing: "EXTERNAL",
|
|
7
|
+
level: "ERROR",
|
|
8
|
+
name: "external_source_incremental_no_delete_path",
|
|
9
|
+
remediation: "Add `reconcileEveryMs` (a periodic full-pull sweep that GCs vanished rows) or `softDeleteColumn` (an upstream tombstone column the incremental pull returns). Incremental ingest can't see a delete otherwise.",
|
|
10
|
+
run: (context) => {
|
|
11
|
+
const findings = [];
|
|
12
|
+
for (const table of context.schema.tables) {
|
|
13
|
+
const source = table.externalSource;
|
|
14
|
+
if (source === void 0) {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (source.unanalyzable) {
|
|
18
|
+
findings.push(
|
|
19
|
+
emit(externalSourceIncrementalNoDeletePath, {
|
|
20
|
+
cacheKey: `external_source_incremental_no_delete_path:${table.name}`,
|
|
21
|
+
detail: `Table \`${table.name}\`'s \`.source(...)\` config is not a static object literal, so its \`mode\`/delete-visibility can't be verified. If it is \`mode: "incremental"\`, confirm it declares \`reconcileEveryMs\` or \`softDeleteColumn\` — an incremental source without one accumulates phantom rows on every upstream delete.`,
|
|
22
|
+
level: "WARN",
|
|
23
|
+
metadata: { table: table.name }
|
|
24
|
+
})
|
|
25
|
+
);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (source.mode !== "incremental" || source.hasReconcile || source.hasSoftDelete) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
findings.push(
|
|
32
|
+
emit(externalSourceIncrementalNoDeletePath, {
|
|
33
|
+
cacheKey: `external_source_incremental_no_delete_path:${table.name}`,
|
|
34
|
+
detail: `Table \`${table.name}\` is \`.source({ mode: "incremental" })\` but declares neither \`reconcileEveryMs\` nor \`softDeleteColumn\` — an incremental pull never sees upstream deletes, so the materialized table would accumulate phantom rows. Add one of the two delete-visibility paths.`,
|
|
35
|
+
metadata: { table: table.name }
|
|
36
|
+
})
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return findings;
|
|
40
|
+
},
|
|
41
|
+
source: "static",
|
|
42
|
+
title: "Incremental sourced table has no delete-visibility path"
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export { externalSourceIncrementalNoDeletePath as default };
|
|
@@ -30,11 +30,8 @@ const fromServerSchema = (schema) => {
|
|
|
30
30
|
return {
|
|
31
31
|
externallyManaged: table.isExternallyManaged ?? false,
|
|
32
32
|
externalSource: table.externalSource ? {
|
|
33
|
-
// `reconcileEveryMs` is not on the typed `.source()`
|
|
34
|
-
// surface today; read it through a widening cast so an
|
|
35
|
-
// untyped JS schema that still carries the key feeds the IR
|
|
36
|
-
// the same way the AST feeder does.
|
|
37
33
|
hasReconcile: table.externalSource.reconcileEveryMs !== void 0,
|
|
34
|
+
hasSoftDelete: table.externalSource.softDeleteColumn !== void 0,
|
|
38
35
|
hasTenantBy: table.externalSource.tenantBy !== void 0,
|
|
39
36
|
mode: table.externalSource.mode
|
|
40
37
|
} : void 0,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/advisor",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.29",
|
|
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.5",
|
|
50
|
-
"@lunora/server": "1.0.0-alpha.
|
|
50
|
+
"@lunora/server": "1.0.0-alpha.26"
|
|
51
51
|
},
|
|
52
52
|
"engines": {
|
|
53
53
|
"node": "^22.15.0 || >=24.11.0"
|