@lunora/advisor 1.0.0-alpha.17 → 1.0.0-alpha.19
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/LICENSE.md +6 -0
- package/dist/index.d.mts +67 -1
- package/dist/index.d.ts +67 -1
- package/dist/index.mjs +3 -1
- package/dist/packem_shared/queueWithoutDlq-CSkGNb_0.mjs +41 -0
- package/package.json +2 -2
package/LICENSE.md
CHANGED
|
@@ -103,3 +103,9 @@ Unless required by applicable law or agreed to in writing, software distributed
|
|
|
103
103
|
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
104
104
|
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
105
105
|
specific language governing permissions and limitations under the License.
|
|
106
|
+
|
|
107
|
+
<!-- DEPENDENCIES -->
|
|
108
|
+
<!-- /DEPENDENCIES -->
|
|
109
|
+
|
|
110
|
+
<!-- TYPE_DEPENDENCIES -->
|
|
111
|
+
<!-- /TYPE_DEPENDENCIES -->
|
package/dist/index.d.mts
CHANGED
|
@@ -817,6 +817,45 @@ interface AdvisorQueryRead {
|
|
|
817
817
|
table: string;
|
|
818
818
|
}
|
|
819
819
|
/**
|
|
820
|
+
* The queue-shaped input the `queue_*` lints consume, produced by the codegen
|
|
821
|
+
* feeder — one per `defineQueue` export in `lunora/queues.ts`. Runtime callers
|
|
822
|
+
* don't supply it, so the queue lints simply find nothing there.
|
|
823
|
+
*
|
|
824
|
+
* A structural subset of codegen's `QueueIR`, so the feeder passes the IR array
|
|
825
|
+
* straight through without conversion (mirrors how `AdvisorWorkflow` tracks
|
|
826
|
+
* `WorkflowIR` and `AdvisorContainer` tracks `ContainerIR`).
|
|
827
|
+
*/
|
|
828
|
+
/**
|
|
829
|
+
* The push-consumer batch/retry tuning a queue lint inspects — the subset of
|
|
830
|
+
* `QueueIR["tuning"]` mirrored onto the wrangler `queues.consumers[]` entry.
|
|
831
|
+
*/
|
|
832
|
+
interface AdvisorQueueTuning {
|
|
833
|
+
/**
|
|
834
|
+
* The wrangler name of the dead-letter queue exhausted messages are routed
|
|
835
|
+
* to. `undefined` when none is declared — a message that exhausts its
|
|
836
|
+
* retries is then dropped and permanently lost.
|
|
837
|
+
*/
|
|
838
|
+
deadLetterQueue?: string;
|
|
839
|
+
/** Max delivery retries before a message is dead-lettered/dropped (Cloudflare default 3). */
|
|
840
|
+
maxRetries?: number;
|
|
841
|
+
}
|
|
842
|
+
/** One queue declared via a `defineQueue()` export in `lunora/queues.ts`. */
|
|
843
|
+
interface AdvisorQueue {
|
|
844
|
+
/** The `lunora/queues.ts` export name, e.g. `notifications`. */
|
|
845
|
+
exportName: string;
|
|
846
|
+
/** How the queue is consumed: `"push"` (a worker `queue()` handler) or `"pull"` (external HTTP). */
|
|
847
|
+
mode: "pull" | "push";
|
|
848
|
+
/**
|
|
849
|
+
* The stable wrangler queue name (kebab-cased export name unless a `name:`
|
|
850
|
+
* literal overrides it). Used to recognise a queue that is itself another
|
|
851
|
+
* queue's `deadLetterQueue` target — a terminal sink that must not be
|
|
852
|
+
* flagged for lacking its own DLQ.
|
|
853
|
+
*/
|
|
854
|
+
name: string;
|
|
855
|
+
/** Push-consumer batch/retry tuning; the `deadLetterQueue`/`maxRetries` the queue lints read. */
|
|
856
|
+
tuning: AdvisorQueueTuning;
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
820
859
|
* One `ctx.r2sql` access discovered lexically inside a `query(...)` or
|
|
821
860
|
* `mutation(...)` handler body — the input the `r2sql_outside_action` lint
|
|
822
861
|
* consumes. Produced by the codegen feeder, which walks each exported function's
|
|
@@ -1711,6 +1750,13 @@ interface LintContext {
|
|
|
1711
1750
|
*/
|
|
1712
1751
|
queries?: ReadonlyArray<AdvisorQueryRead>;
|
|
1713
1752
|
/**
|
|
1753
|
+
* Queues declared via `defineQueue` exports in `lunora/queues.ts` — the
|
|
1754
|
+
* declaration-side input for the `queue_*` lints (`queue_without_dlq`).
|
|
1755
|
+
* Supplied by the codegen feeder; absent for runtime callers, where the
|
|
1756
|
+
* queue lints find nothing.
|
|
1757
|
+
*/
|
|
1758
|
+
queues?: ReadonlyArray<AdvisorQueue>;
|
|
1759
|
+
/**
|
|
1714
1760
|
* R2 SQL `ctx.r2sql` accesses discovered lexically inside `query`/`mutation`
|
|
1715
1761
|
* handler bodies — the `r2sql_outside_action` input. Supplied by the codegen
|
|
1716
1762
|
* feeder, which omits `action` handlers (where `ctx.r2sql` is the typed,
|
|
@@ -3035,6 +3081,26 @@ declare const publicMutationWithoutRatelimit: Lint;
|
|
|
3035
3081
|
*/
|
|
3036
3082
|
declare const publicTableRlsOptoutConfusion: Lint;
|
|
3037
3083
|
/**
|
|
3084
|
+
* Flags a declared queue — push or pull — that has no dead-letter queue.
|
|
3085
|
+
*
|
|
3086
|
+
* A Cloudflare Queues consumer retries a failing message up to `maxRetries`
|
|
3087
|
+
* times (default 3 — roughly four total delivery attempts); once that budget is
|
|
3088
|
+
* exhausted, a message with no `deadLetterQueue` is **deleted permanently** with
|
|
3089
|
+
* no record an operator can inspect. Routing exhausted messages to a DLQ turns
|
|
3090
|
+
* silent data loss into a backlog you can inspect, alert on, and replay. Hence
|
|
3091
|
+
* `WARN`/`INTERNAL`: an operator-facing reliability nudge, not a hard error — a
|
|
3092
|
+
* genuinely fire-and-forget queue may accept the loss.
|
|
3093
|
+
*
|
|
3094
|
+
* A queue that is itself some other queue's `deadLetterQueue` target is skipped:
|
|
3095
|
+
* a DLQ is a terminal sink and requiring it to have its own DLQ would recurse
|
|
3096
|
+
* forever (and mis-flag the best-practice scaffold, which pairs a queue with a
|
|
3097
|
+
* dedicated DLQ consumer).
|
|
3098
|
+
*
|
|
3099
|
+
* Only runs when the declaration feeder supplied evidence (`context.queues`
|
|
3100
|
+
* present); a runtime caller flags nothing.
|
|
3101
|
+
*/
|
|
3102
|
+
declare const queueWithoutDlq: Lint;
|
|
3103
|
+
/**
|
|
3038
3104
|
* Flags an R2 SQL `ctx.r2sql` access inside a `query(...)` or `mutation(...)`
|
|
3039
3105
|
* handler body.
|
|
3040
3106
|
*
|
|
@@ -3536,4 +3602,4 @@ interface RunAdvisorOptions {
|
|
|
3536
3602
|
* `static` lints at build time and defer `runtime` lints to a live shard.
|
|
3537
3603
|
*/
|
|
3538
3604
|
declare const runAdvisor: (context: LintContext, options?: RunAdvisorOptions) => Finding[];
|
|
3539
|
-
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 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, 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, 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 };
|
|
3605
|
+
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, 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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -817,6 +817,45 @@ interface AdvisorQueryRead {
|
|
|
817
817
|
table: string;
|
|
818
818
|
}
|
|
819
819
|
/**
|
|
820
|
+
* The queue-shaped input the `queue_*` lints consume, produced by the codegen
|
|
821
|
+
* feeder — one per `defineQueue` export in `lunora/queues.ts`. Runtime callers
|
|
822
|
+
* don't supply it, so the queue lints simply find nothing there.
|
|
823
|
+
*
|
|
824
|
+
* A structural subset of codegen's `QueueIR`, so the feeder passes the IR array
|
|
825
|
+
* straight through without conversion (mirrors how `AdvisorWorkflow` tracks
|
|
826
|
+
* `WorkflowIR` and `AdvisorContainer` tracks `ContainerIR`).
|
|
827
|
+
*/
|
|
828
|
+
/**
|
|
829
|
+
* The push-consumer batch/retry tuning a queue lint inspects — the subset of
|
|
830
|
+
* `QueueIR["tuning"]` mirrored onto the wrangler `queues.consumers[]` entry.
|
|
831
|
+
*/
|
|
832
|
+
interface AdvisorQueueTuning {
|
|
833
|
+
/**
|
|
834
|
+
* The wrangler name of the dead-letter queue exhausted messages are routed
|
|
835
|
+
* to. `undefined` when none is declared — a message that exhausts its
|
|
836
|
+
* retries is then dropped and permanently lost.
|
|
837
|
+
*/
|
|
838
|
+
deadLetterQueue?: string;
|
|
839
|
+
/** Max delivery retries before a message is dead-lettered/dropped (Cloudflare default 3). */
|
|
840
|
+
maxRetries?: number;
|
|
841
|
+
}
|
|
842
|
+
/** One queue declared via a `defineQueue()` export in `lunora/queues.ts`. */
|
|
843
|
+
interface AdvisorQueue {
|
|
844
|
+
/** The `lunora/queues.ts` export name, e.g. `notifications`. */
|
|
845
|
+
exportName: string;
|
|
846
|
+
/** How the queue is consumed: `"push"` (a worker `queue()` handler) or `"pull"` (external HTTP). */
|
|
847
|
+
mode: "pull" | "push";
|
|
848
|
+
/**
|
|
849
|
+
* The stable wrangler queue name (kebab-cased export name unless a `name:`
|
|
850
|
+
* literal overrides it). Used to recognise a queue that is itself another
|
|
851
|
+
* queue's `deadLetterQueue` target — a terminal sink that must not be
|
|
852
|
+
* flagged for lacking its own DLQ.
|
|
853
|
+
*/
|
|
854
|
+
name: string;
|
|
855
|
+
/** Push-consumer batch/retry tuning; the `deadLetterQueue`/`maxRetries` the queue lints read. */
|
|
856
|
+
tuning: AdvisorQueueTuning;
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
820
859
|
* One `ctx.r2sql` access discovered lexically inside a `query(...)` or
|
|
821
860
|
* `mutation(...)` handler body — the input the `r2sql_outside_action` lint
|
|
822
861
|
* consumes. Produced by the codegen feeder, which walks each exported function's
|
|
@@ -1711,6 +1750,13 @@ interface LintContext {
|
|
|
1711
1750
|
*/
|
|
1712
1751
|
queries?: ReadonlyArray<AdvisorQueryRead>;
|
|
1713
1752
|
/**
|
|
1753
|
+
* Queues declared via `defineQueue` exports in `lunora/queues.ts` — the
|
|
1754
|
+
* declaration-side input for the `queue_*` lints (`queue_without_dlq`).
|
|
1755
|
+
* Supplied by the codegen feeder; absent for runtime callers, where the
|
|
1756
|
+
* queue lints find nothing.
|
|
1757
|
+
*/
|
|
1758
|
+
queues?: ReadonlyArray<AdvisorQueue>;
|
|
1759
|
+
/**
|
|
1714
1760
|
* R2 SQL `ctx.r2sql` accesses discovered lexically inside `query`/`mutation`
|
|
1715
1761
|
* handler bodies — the `r2sql_outside_action` input. Supplied by the codegen
|
|
1716
1762
|
* feeder, which omits `action` handlers (where `ctx.r2sql` is the typed,
|
|
@@ -3035,6 +3081,26 @@ declare const publicMutationWithoutRatelimit: Lint;
|
|
|
3035
3081
|
*/
|
|
3036
3082
|
declare const publicTableRlsOptoutConfusion: Lint;
|
|
3037
3083
|
/**
|
|
3084
|
+
* Flags a declared queue — push or pull — that has no dead-letter queue.
|
|
3085
|
+
*
|
|
3086
|
+
* A Cloudflare Queues consumer retries a failing message up to `maxRetries`
|
|
3087
|
+
* times (default 3 — roughly four total delivery attempts); once that budget is
|
|
3088
|
+
* exhausted, a message with no `deadLetterQueue` is **deleted permanently** with
|
|
3089
|
+
* no record an operator can inspect. Routing exhausted messages to a DLQ turns
|
|
3090
|
+
* silent data loss into a backlog you can inspect, alert on, and replay. Hence
|
|
3091
|
+
* `WARN`/`INTERNAL`: an operator-facing reliability nudge, not a hard error — a
|
|
3092
|
+
* genuinely fire-and-forget queue may accept the loss.
|
|
3093
|
+
*
|
|
3094
|
+
* A queue that is itself some other queue's `deadLetterQueue` target is skipped:
|
|
3095
|
+
* a DLQ is a terminal sink and requiring it to have its own DLQ would recurse
|
|
3096
|
+
* forever (and mis-flag the best-practice scaffold, which pairs a queue with a
|
|
3097
|
+
* dedicated DLQ consumer).
|
|
3098
|
+
*
|
|
3099
|
+
* Only runs when the declaration feeder supplied evidence (`context.queues`
|
|
3100
|
+
* present); a runtime caller flags nothing.
|
|
3101
|
+
*/
|
|
3102
|
+
declare const queueWithoutDlq: Lint;
|
|
3103
|
+
/**
|
|
3038
3104
|
* Flags an R2 SQL `ctx.r2sql` access inside a `query(...)` or `mutation(...)`
|
|
3039
3105
|
* handler body.
|
|
3040
3106
|
*
|
|
@@ -3536,4 +3602,4 @@ interface RunAdvisorOptions {
|
|
|
3536
3602
|
* `static` lints at build time and defer `runtime` lints to a live shard.
|
|
3537
3603
|
*/
|
|
3538
3604
|
declare const runAdvisor: (context: LintContext, options?: RunAdvisorOptions) => Finding[];
|
|
3539
|
-
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 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, 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, 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 };
|
|
3605
|
+
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, 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 };
|
package/dist/index.mjs
CHANGED
|
@@ -53,6 +53,7 @@ import privilegedFanoutFromPublicProcedure from './packem_shared/privilegedFanou
|
|
|
53
53
|
import publicArgumentUsesAny from './packem_shared/publicArgumentUsesAny-C71b2NCf.mjs';
|
|
54
54
|
import publicMutationWithoutRatelimit from './packem_shared/publicMutationWithoutRatelimit-xBpJ6GWK.mjs';
|
|
55
55
|
import publicTableRlsOptoutConfusion from './packem_shared/publicTableRlsOptoutConfusion-DJ5GFSRD.mjs';
|
|
56
|
+
import queueWithoutDlq from './packem_shared/queueWithoutDlq-CSkGNb_0.mjs';
|
|
56
57
|
import r2sqlOutsideAction from './packem_shared/r2sqlOutsideAction-CtqxvMuV.mjs';
|
|
57
58
|
import ratelimitDefaultMemoryStore from './packem_shared/ratelimitDefaultMemoryStore-BISChG5C.mjs';
|
|
58
59
|
import ratelimitKeySpoofableOrGlobal from './packem_shared/ratelimitKeySpoofableOrGlobal-DqlHYQQ3.mjs';
|
|
@@ -97,6 +98,7 @@ const STATIC_LINTS = [
|
|
|
97
98
|
duplicateIndex,
|
|
98
99
|
tableWithoutInsert,
|
|
99
100
|
workflowUnused,
|
|
101
|
+
queueWithoutDlq,
|
|
100
102
|
filterWithoutIndex,
|
|
101
103
|
shapeTargetsGlobalTable,
|
|
102
104
|
mutatorFullRowReplace,
|
|
@@ -176,4 +178,4 @@ const runAdvisor = (context, options = {}) => {
|
|
|
176
178
|
return findings;
|
|
177
179
|
};
|
|
178
180
|
|
|
179
|
-
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, duplicateIndex, emptyIndex, 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, 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 };
|
|
181
|
+
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, duplicateIndex, emptyIndex, 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,41 @@
|
|
|
1
|
+
import { e as emit } from './finding-Dm_zvzS1.mjs';
|
|
2
|
+
|
|
3
|
+
const queueWithoutDlq = {
|
|
4
|
+
categories: ["SCHEMA"],
|
|
5
|
+
description: "A queue consumer drops a message once it exhausts `maxRetries` (default 3) delivery attempts. Without a `deadLetterQueue`, that message is deleted permanently with no record — route exhausted messages to a DLQ so you can inspect, alert on, and replay them.",
|
|
6
|
+
facing: "INTERNAL",
|
|
7
|
+
level: "WARN",
|
|
8
|
+
name: "queue_without_dlq",
|
|
9
|
+
remediation: 'Add `deadLetterQueue: "<name>-dlq"` to the `defineQueue({...})` options and declare a consumer for that queue so exhausted messages are inspectable (an unconsumed DLQ still expires at the retention window). `vis generate lunora-queue` with the best-practice setup scaffolds both. If the queue is fire-and-forget and message loss is acceptable, this advisory can be ignored.',
|
|
10
|
+
run: (context) => {
|
|
11
|
+
if (context.queues === void 0) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
const dlqTargets = new Set(
|
|
15
|
+
context.queues.map((queue) => queue.tuning.deadLetterQueue).filter((name) => name !== void 0 && name !== "")
|
|
16
|
+
);
|
|
17
|
+
const findings = [];
|
|
18
|
+
for (const queue of context.queues) {
|
|
19
|
+
const dlq = queue.tuning.deadLetterQueue;
|
|
20
|
+
if (dlq !== void 0 && dlq !== "") {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (dlqTargets.has(queue.name)) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const maxRetries = typeof queue.tuning.maxRetries === "number" ? queue.tuning.maxRetries : 3;
|
|
27
|
+
findings.push(
|
|
28
|
+
emit(queueWithoutDlq, {
|
|
29
|
+
cacheKey: `queue_without_dlq:${queue.exportName}`,
|
|
30
|
+
detail: `Queue "${queue.exportName}" declares no \`deadLetterQueue\`, so a message that exhausts its retries (\`maxRetries\` = ${String(maxRetries)}, ~${String(maxRetries + 1)} delivery attempts) is dropped and permanently lost.`,
|
|
31
|
+
metadata: { maxRetries, mode: queue.mode, queue: queue.exportName }
|
|
32
|
+
})
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
return findings;
|
|
36
|
+
},
|
|
37
|
+
source: "static",
|
|
38
|
+
title: "Queue has no dead-letter queue"
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export { queueWithoutDlq as default };
|
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.19",
|
|
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.1",
|
|
50
|
-
"@lunora/server": "1.0.0-alpha.
|
|
50
|
+
"@lunora/server": "1.0.0-alpha.16"
|
|
51
51
|
},
|
|
52
52
|
"engines": {
|
|
53
53
|
"node": "^22.15.0 || >=24.11.0"
|