Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions crates/pgls_splinter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ serde.workspace = true
serde_json.workspace = true
sqlx.workspace = true

[build-dependencies]
ureq = "2.10"

[dev-dependencies]
insta.workspace = true
pgls_console.workspace = true
Expand Down
214 changes: 0 additions & 214 deletions crates/pgls_splinter/build.rs

This file was deleted.

10 changes: 7 additions & 3 deletions crates/pgls_splinter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,12 @@ pub async fn run_splinter(

for rule_name in &collector.enabled_rules {
// Skip Supabase-specific rules if Supabase roles don't exist
if !has_supabase_roles && crate::registry::rule_requires_supabase(rule_name) {
continue;
if !has_supabase_roles {
if let Some(metadata) = crate::registry::get_rule_metadata(rule_name) {
if metadata.requires_supabase {
continue;
}
}
}

// Get embedded SQL content (compile-time included)
Expand All @@ -99,7 +103,7 @@ pub async fn run_splinter(
// Ensure all queries are wrapped for valid UNION ALL syntax
let processed_queries: Vec<String> = sql_queries
.iter()
.map(|sql| {
.map(|sql: &&str| {
let trimmed = sql.trim();
// Wrap in parentheses if not already wrapped
if trimmed.starts_with('(') && trimmed.ends_with(')') {
Expand Down
30 changes: 30 additions & 0 deletions crates/pgls_splinter/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

#![doc = r" Generated file, do not edit by hand, see `xtask/codegen`"]
use pgls_analyse::RegistryVisitor;
#[doc = r" Metadata for a splinter rule"]
#[derive(Debug, Clone, Copy)]
pub struct SplinterRuleMetadata {
#[doc = r" Description of what the rule detects"]
pub description: &'static str,
#[doc = r" URL to documentation/remediation guide"]
pub remediation: &'static str,
#[doc = r" Whether this rule requires Supabase roles (anon, authenticated, service_role)"]
pub requires_supabase: bool,
}
#[doc = r" Visit all splinter rules using the visitor pattern"]
#[doc = r" This is called during registry building to collect enabled rules"]
pub fn visit_registry<V: RegistryVisitor>(registry: &mut V) {
Expand Down Expand Up @@ -151,6 +161,25 @@ pub fn get_sql_content(rule_name: &str) -> Option<&'static str> {
_ => None,
}
}
#[doc = r" Get metadata fields for a rule (camelCase name)"]
#[doc = r" Returns (description, remediation, requires_supabase) tuple"]
#[doc = r""]
#[doc = r" This calls the trait constants from the generated rule types"]
pub fn get_rule_metadata_fields(rule_name: &str) -> Option<(&'static str, &'static str, bool)> {
match rule_name { "authRlsInitplan" => Some ((< crate :: rules :: performance :: auth_rls_initplan :: AuthRlsInitplan as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: performance :: auth_rls_initplan :: AuthRlsInitplan as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: performance :: auth_rls_initplan :: AuthRlsInitplan as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "authUsersExposed" => Some ((< crate :: rules :: security :: auth_users_exposed :: AuthUsersExposed as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: security :: auth_users_exposed :: AuthUsersExposed as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: security :: auth_users_exposed :: AuthUsersExposed as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "duplicateIndex" => Some ((< crate :: rules :: performance :: duplicate_index :: DuplicateIndex as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: performance :: duplicate_index :: DuplicateIndex as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: performance :: duplicate_index :: DuplicateIndex as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "extensionInPublic" => Some ((< crate :: rules :: security :: extension_in_public :: ExtensionInPublic as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: security :: extension_in_public :: ExtensionInPublic as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: security :: extension_in_public :: ExtensionInPublic as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "extensionVersionsOutdated" => Some ((< crate :: rules :: security :: extension_versions_outdated :: ExtensionVersionsOutdated as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: security :: extension_versions_outdated :: ExtensionVersionsOutdated as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: security :: extension_versions_outdated :: ExtensionVersionsOutdated as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "fkeyToAuthUnique" => Some ((< crate :: rules :: security :: fkey_to_auth_unique :: FkeyToAuthUnique as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: security :: fkey_to_auth_unique :: FkeyToAuthUnique as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: security :: fkey_to_auth_unique :: FkeyToAuthUnique as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "foreignTableInApi" => Some ((< crate :: rules :: security :: foreign_table_in_api :: ForeignTableInApi as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: security :: foreign_table_in_api :: ForeignTableInApi as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: security :: foreign_table_in_api :: ForeignTableInApi as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "functionSearchPathMutable" => Some ((< crate :: rules :: security :: function_search_path_mutable :: FunctionSearchPathMutable as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: security :: function_search_path_mutable :: FunctionSearchPathMutable as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: security :: function_search_path_mutable :: FunctionSearchPathMutable as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "insecureQueueExposedInApi" => Some ((< crate :: rules :: security :: insecure_queue_exposed_in_api :: InsecureQueueExposedInApi as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: security :: insecure_queue_exposed_in_api :: InsecureQueueExposedInApi as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: security :: insecure_queue_exposed_in_api :: InsecureQueueExposedInApi as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "materializedViewInApi" => Some ((< crate :: rules :: security :: materialized_view_in_api :: MaterializedViewInApi as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: security :: materialized_view_in_api :: MaterializedViewInApi as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: security :: materialized_view_in_api :: MaterializedViewInApi as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "multiplePermissivePolicies" => Some ((< crate :: rules :: performance :: multiple_permissive_policies :: MultiplePermissivePolicies as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: performance :: multiple_permissive_policies :: MultiplePermissivePolicies as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: performance :: multiple_permissive_policies :: MultiplePermissivePolicies as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "noPrimaryKey" => Some ((< crate :: rules :: performance :: no_primary_key :: NoPrimaryKey as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: performance :: no_primary_key :: NoPrimaryKey as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: performance :: no_primary_key :: NoPrimaryKey as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "policyExistsRlsDisabled" => Some ((< crate :: rules :: security :: policy_exists_rls_disabled :: PolicyExistsRlsDisabled as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: security :: policy_exists_rls_disabled :: PolicyExistsRlsDisabled as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: security :: policy_exists_rls_disabled :: PolicyExistsRlsDisabled as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "rlsDisabledInPublic" => Some ((< crate :: rules :: security :: rls_disabled_in_public :: RlsDisabledInPublic as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: security :: rls_disabled_in_public :: RlsDisabledInPublic as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: security :: rls_disabled_in_public :: RlsDisabledInPublic as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "rlsEnabledNoPolicy" => Some ((< crate :: rules :: security :: rls_enabled_no_policy :: RlsEnabledNoPolicy as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: security :: rls_enabled_no_policy :: RlsEnabledNoPolicy as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: security :: rls_enabled_no_policy :: RlsEnabledNoPolicy as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "rlsReferencesUserMetadata" => Some ((< crate :: rules :: security :: rls_references_user_metadata :: RlsReferencesUserMetadata as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: security :: rls_references_user_metadata :: RlsReferencesUserMetadata as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: security :: rls_references_user_metadata :: RlsReferencesUserMetadata as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "securityDefinerView" => Some ((< crate :: rules :: security :: security_definer_view :: SecurityDefinerView as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: security :: security_definer_view :: SecurityDefinerView as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: security :: security_definer_view :: SecurityDefinerView as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "tableBloat" => Some ((< crate :: rules :: performance :: table_bloat :: TableBloat as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: performance :: table_bloat :: TableBloat as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: performance :: table_bloat :: TableBloat as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "unindexedForeignKeys" => Some ((< crate :: rules :: performance :: unindexed_foreign_keys :: UnindexedForeignKeys as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: performance :: unindexed_foreign_keys :: UnindexedForeignKeys as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: performance :: unindexed_foreign_keys :: UnindexedForeignKeys as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "unsupportedRegTypes" => Some ((< crate :: rules :: security :: unsupported_reg_types :: UnsupportedRegTypes as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: security :: unsupported_reg_types :: UnsupportedRegTypes as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: security :: unsupported_reg_types :: UnsupportedRegTypes as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , "unusedIndex" => Some ((< crate :: rules :: performance :: unused_index :: UnusedIndex as crate :: rule :: SplinterRule > :: DESCRIPTION , < crate :: rules :: performance :: unused_index :: UnusedIndex as crate :: rule :: SplinterRule > :: REMEDIATION , < crate :: rules :: performance :: unused_index :: UnusedIndex as crate :: rule :: SplinterRule > :: REQUIRES_SUPABASE ,)) , _ => None , }
}
#[doc = r" Get metadata for a rule (camelCase name)"]
#[doc = r" Returns None if rule not found"]
#[doc = r""]
#[doc = r" This provides structured access to rule metadata by calling trait constants"]
pub fn get_rule_metadata(rule_name: &str) -> Option<SplinterRuleMetadata> {
let (description, remediation, requires_supabase) = get_rule_metadata_fields(rule_name)?;
Some(SplinterRuleMetadata {
description,
remediation,
requires_supabase,
})
}
#[doc = r" Map rule name from SQL result (snake_case) to diagnostic category"]
#[doc = r" Returns None if rule not found"]
#[doc = r""]
Expand Down Expand Up @@ -225,6 +254,7 @@ pub fn get_rule_category(rule_name: &str) -> Option<&'static ::pgls_diagnostics:
}
#[doc = r" Check if a rule requires Supabase roles (anon, authenticated, service_role)"]
#[doc = r" Rules that require Supabase should be filtered out if these roles don't exist"]
#[deprecated(note = "Use get_rule_metadata() instead")]
pub fn rule_requires_supabase(rule_name: &str) -> bool {
match rule_name {
"authRlsInitplan" => true,
Expand Down
Loading