Documentation
¶
Overview ¶
Package database — drill.go: high-level DR drill orchestration.
The `nself backup drill` command wraps the existing RestoreDrill primitive (restore_drill.go) with three production concerns the bare drill primitive does not address:
- RTO measurement: total wall-clock from "drill start" to "smoke checks pass", broken into download / decrypt / restore / verify phases. The target per STRAT-11 is 4 hours; anything longer needs investigation.
- Critical-table smoke: row-count assertions on np_users, np_licenses, np_audit_log, np_plugins, np_billing — five tables whose presence is load-bearing for license validation + signup recovery.
- Drill-log emission: an entry in .nself/drill-log.json that the doctor check OPS-DRILL-01 reads to enforce "drill within last 7 days".
The drill never touches production. RestoreDrill restores into a scratch database named <db>_drilltest, runs the smoke suite, then drops the scratch DB. Failure at any phase is reported with the partial timing data so operators can see exactly which phase blew the budget.
This file lives in `database` (not `backup`) to avoid an import cycle — `backup` already imports `database`, so the high-level drill orchestrator must live next to RestoreDrill rather than alongside backup.Create.
Package database provides database and Hasura metadata operations.
Package database provides SQL identifier sanitization helpers to prevent SQL injection in contexts where identifiers (database, schema, table, column names) must be interpolated into SQL statements (positional parameters do not bind identifiers in PostgreSQL).
Index ¶
- Variables
- func ApplyDefaultRLSPolicies(ctx context.Context, cfg *config.Config, schema, table string) error
- func ApplyDir(ctx context.Context, cfg *config.Config, dirPath string) (int, error)
- func ApplyFKIndexes(ctx context.Context, cfg *config.Config, findings []FKIndexInfo) (created int, errs []error)
- func ApplyFile(ctx context.Context, cfg *config.Config, filePath string) (skipped bool, err error)
- func ApplyMetadataFromGit(ctx context.Context, cfg *config.Config, projectDir string, ref string) error
- func ApplyRLSBatch(ctx context.Context, cfg *config.Config, tables []RLSTableInfo) (applied int, skipped int, errs []error)
- func ApplySoftDelete(ctx context.Context, cfg *config.Config, schema, table string) error
- func ApplyTenantRLS(ctx context.Context, dbcfg *config.Config, rlsCfg TenantRLSConfig) error
- func Backup(ctx context.Context, cfg *config.Config, outputPath string) error
- func CheckMigrationIdempotency(sqlContent string) (bool, []string)
- func CompareSnapshots(before, after []byte) (string, error)
- func EnableRLSOnTable(ctx context.Context, cfg *config.Config, schema, table string) error
- func ExportAndCommitMetadata(ctx context.Context, cfg *config.Config, projectDir string, commitMsg string) (string, error)
- func GenerateCrossRegionCronScript(cfg *config.Config, xrCfg CrossRegionBackupConfig) string
- func GenerateDriftMigration(result SchemaDriftResult) (upSQL, downSQL string)
- func GenerateFKIndexSQL(info FKIndexInfo) string
- func GenerateIdempotentVersion(sqlContent string) (converted string, changes []string)
- func GeneratePITRPostgresConf(cfg *config.Config, pitrCfg PITRConfig) string
- func GenerateRollbackSQL(schema, table string) string
- func GenerateSoftDeleteMigration(schema, table string) (upSQL, downSQL string)
- func GenerateTenantRLSSQL(cfg TenantRLSConfig) (string, error)
- func GenerateTrackTableSQL(schema, table string) string
- func HasuraApplyMetadata(ctx context.Context, cfg *config.Config, projectDir string) error
- func HasuraDiffMetadata(ctx context.Context, cfg *config.Config, projectDir string) ([]string, error)
- func HasuraExportMetadata(ctx context.Context, cfg *config.Config) ([]byte, error)
- func HasuraExportToYAML(ctx context.Context, cfg *config.Config, projectDir string) (string, error)
- func HasuraReloadMetadata(ctx context.Context, cfg *config.Config) error
- func HasuraValidatePermissions(ctx context.Context, cfg *config.Config) ([]string, error)
- func InitializeDatabase(ctx context.Context, cfg *config.Config) error
- func MetadataSnapshot(ctx context.Context, cfg *config.Config) ([]byte, error)
- func MigrateDown(ctx context.Context, cfg *config.Config) error
- func MigrateUp(ctx context.Context, cfg *config.Config, plugin string) (int, error)
- func MigrateUpDir(ctx context.Context, cfg *config.Config, dir string) (int, error)
- func MustSanitizeIdentifier(s string) string
- func Open(ctx context.Context, cfg *config.Config) (*sql.DB, error)
- func PITRRestore(ctx context.Context, cfg *config.Config, targetTime string) error
- func PendingMigrations(ctx context.Context, cfg *config.Config, plugin string) ([]string, error)
- func PgBouncerConfigFile(cfg *config.Config) string
- func PgBouncerConnectionURL(cfg *config.Config) string
- func PgBouncerHBAFile(cfg *config.Config) string
- func PgBouncerUserlistFile(cfg *config.Config) string
- func PruneRemoteBackups(ctx context.Context, cfg *config.Config, xrCfg CrossRegionBackupConfig) (pruned int, err error)
- func RecordDrillResult(projectDir string, result RestoreDrillResult) error
- func ResetChecksum(ctx context.Context, cfg *config.Config, migrationID string) error
- func Restore(ctx context.Context, cfg *config.Config, inputPath string) error
- func SanitizeIdentifier(s string) (string, error)
- func Seed(ctx context.Context, cfg *config.Config, file string) error
- func SeedFilter(seedFiles []string, dbEnvSeeds string, currentEnv string) []string
- func SyncBackupToRemote(ctx context.Context, cfg *config.Config, xrCfg CrossRegionBackupConfig) error
- func TestWALArchive(ctx context.Context, cfg *config.Config) error
- func VerifyRestoredDatabase(ctx context.Context, cfg *config.Config, drillDB string) (tables int, rows int64, err error)
- func WritePITRConfig(cfg *config.Config, projectDir string, pitrCfg PITRConfig) error
- func WritePgBouncerConfig(ctx context.Context, cfg *config.Config, projectDir string) error
- type ChecksumMismatch
- type CrossRegionBackupConfig
- type CrossRegionBackupStatus
- type DriftSummary
- type DrillOptions
- type DrillResult
- type FKIndexInfo
- type HasuraGitStatus
- type MetadataDrift
- type MigrationAuditResult
- type MigrationRecord
- type MigrationStatus
- type PITRConfig
- type PITRStatus
- type PgBouncerStatus
- type RLSTableInfo
- type RequiredColumn
- type RestoreDrillResult
- type SchemaDriftResult
- type SoftDeleteInfo
- type TenantRLSConfig
- type TenantRLSPattern
Constants ¶
This section is empty.
Variables ¶
var CriticalTables = []string{
"np_users",
"np_licenses",
"np_audit_log",
"np_plugins",
"np_billing",
}
CriticalTables is the canonical list of np_* tables the drill smoke suite asserts presence on. The five tables here are load-bearing for the most common recovery scenario: license validation + signup pipeline + audit log must survive a restore. Adding a table here makes drill stricter; remove only with explicit user approval (these are the smoke-check baseline).
var Theme25RequiredColumns = []RequiredColumn{ {Name: "id", DataType: "uuid", Required: true, Description: "UUID primary key"}, {Name: "created_at", DataType: "timestamp with time zone", Required: true, Description: "creation timestamp"}, {Name: "updated_at", DataType: "timestamp with time zone", Required: true, Description: "last update timestamp"}, {Name: "user_id", DataType: "uuid", Required: false, Description: "owner reference to auth.users"}, {Name: "deleted_at", DataType: "timestamp with time zone", Required: false, Description: "soft-delete timestamp"}, }
Theme25RequiredColumns are the 5 columns mandated by Theme 25.
Functions ¶
func ApplyDefaultRLSPolicies ¶ added in v1.0.9
ApplyDefaultRLSPolicies creates standard Hasura-compatible RLS policies on the given table. Policies use current_setting('hasura.user', true) for user identity and current_setting('hasura.role', true) for admin bypass.
If the table has no user_id column the user-based predicates are omitted and only admin-bypass policies are applied.
Schema and table names must originate from AuditRLS (pg_catalog validated).
func ApplyDir ¶ added in v1.1.1
ApplyDir is an alias for MigrateUpDir with the name expected by the task spec (G-008). Both functions apply all .sql files in the given directory in lexicographic order, skipping files already recorded in schema_versions.
func ApplyFKIndexes ¶ added in v1.0.9
func ApplyFKIndexes(ctx context.Context, cfg *config.Config, findings []FKIndexInfo) (created int, errs []error)
ApplyFKIndexes creates missing indexes for all FK columns lacking one. Returns count of indexes created and any errors.
func ApplyFile ¶ added in v1.1.1
ApplyFile applies a single external SQL migration file and records it in schema_versions by filename + SHA-256 checksum (G-008).
Double-apply protection: if a file with the same filename is already present in schema_versions, the function logs the skip and returns (true, nil). The checksum is stored in nself_ops.migrations for audit purposes.
This enables plugin-claw external RLS migrations to be applied via CLI without requiring 'nself db shell' as a workaround.
func ApplyMetadataFromGit ¶ added in v1.0.9
func ApplyMetadataFromGit(ctx context.Context, cfg *config.Config, projectDir string, ref string) error
ApplyMetadataFromGit checks out the metadata files at the given git ref and then applies them via the standard metadata apply mechanism. ref can be a branch name, tag, or commit hash.
func ApplyRLSBatch ¶ added in v1.0.9
func ApplyRLSBatch(ctx context.Context, cfg *config.Config, tables []RLSTableInfo) (applied int, skipped int, errs []error)
ApplyRLSBatch runs EnableRLSOnTable and ApplyDefaultRLSPolicies on each table in the provided list. Tables that already have RLS enabled and at least one policy are skipped. Returns counts of applied and skipped tables along with any non-fatal errors encountered.
func ApplySoftDelete ¶ added in v1.0.9
ApplySoftDelete runs the soft-delete migration for a specific table.
func ApplyTenantRLS ¶ added in v1.0.9
ApplyTenantRLS generates the RLS SQL for the given TenantRLSConfig and pipes it to the postgres container via psql.
func Backup ¶
Backup runs pg_dump inside the project's postgres container and streams the output directly to a file on disk. The custom format (-Fc) is used so the dump can be restored with pg_restore.
If outputPath is empty, a timestamped filename is generated under a "backups/" directory relative to the current working directory.
func CheckMigrationIdempotency ¶ added in v1.0.9
CheckMigrationIdempotency analyzes SQL content for idempotent patterns. Returns true if the migration appears safe to re-run. Idempotent indicators: IF NOT EXISTS, IF EXISTS, CREATE OR REPLACE Non-idempotent: bare CREATE TABLE, ALTER TABLE ... ADD COLUMN without IF NOT EXISTS
func CompareSnapshots ¶ added in v1.0.9
CompareSnapshots returns a human-readable diff between two metadata snapshots. It compares table lists extracted from the sources and reports additions and removals.
func EnableRLSOnTable ¶ added in v1.0.9
EnableRLSOnTable runs ALTER TABLE to enable and force row-level security on the given schema.table. Schema and table names must come from AuditRLS output (validated against pg_catalog) and are quoted to prevent SQL injection.
func ExportAndCommitMetadata ¶ added in v1.0.9
func ExportAndCommitMetadata(ctx context.Context, cfg *config.Config, projectDir string, commitMsg string) (string, error)
ExportAndCommitMetadata exports Hasura metadata and creates a git commit. commitMsg is the commit message; if empty, a default message is generated. Returns the commit hash on success.
func GenerateCrossRegionCronScript ¶ added in v1.0.9
func GenerateCrossRegionCronScript(cfg *config.Config, xrCfg CrossRegionBackupConfig) string
GenerateCrossRegionCronScript generates a shell script suitable for use in a Docker cron container for daily cross-region backups.
func GenerateDriftMigration ¶ added in v1.0.9
func GenerateDriftMigration(result SchemaDriftResult) (upSQL, downSQL string)
GenerateDriftMigration generates SQL to add missing columns to a table. Returns up.sql and down.sql content.
func GenerateFKIndexSQL ¶ added in v1.0.9
func GenerateFKIndexSQL(info FKIndexInfo) string
GenerateFKIndexSQL generates CREATE INDEX SQL for a missing FK index.
func GenerateIdempotentVersion ¶ added in v1.0.9
GenerateIdempotentVersion takes migration SQL and attempts to convert it to an idempotent form by adding IF NOT EXISTS clauses where missing. Returns the converted SQL and a list of conversions made.
func GeneratePITRPostgresConf ¶ added in v1.0.9
func GeneratePITRPostgresConf(cfg *config.Config, pitrCfg PITRConfig) string
GeneratePITRPostgresConf generates the postgresql.conf snippet needed for PITR. Returns the configuration as a string ready to append to postgresql.conf.
func GenerateRollbackSQL ¶ added in v1.0.9
GenerateRollbackSQL returns SQL that removes all four standard RLS policies and disables row-level security on the given schema.table. The schema and table names must originate from AuditRLS (pg_catalog validated).
func GenerateSoftDeleteMigration ¶ added in v1.0.9
GenerateSoftDeleteMigration generates the SQL to add soft-delete support to a table: adds deleted_at TIMESTAMPTZ column, index, and creates a {table}_active view that filters WHERE deleted_at IS NULL. Returns up.sql and down.sql content.
func GenerateTenantRLSSQL ¶ added in v1.0.9
func GenerateTenantRLSSQL(cfg TenantRLSConfig) (string, error)
GenerateTenantRLSSQL generates the complete SQL block (ENABLE RLS + FORCE RLS + DROP/CREATE policies) for the given TenantRLSConfig. The returned SQL is safe to pipe directly to psql.
func GenerateTrackTableSQL ¶ added in v1.0.9
GenerateTrackTableSQL generates a comment block describing how to track a new table in Hasura metadata. It returns a YAML snippet and CLI hint rather than raw SQL because table tracking is a Hasura metadata operation.
func HasuraApplyMetadata ¶
HasuraApplyMetadata applies Hasura metadata from projectDir.
It supports two metadata formats:
YAML directory format (standard Hasura CLI): projectDir/hasura/metadata/ Tables use !include directives referencing individual YAML files. This format is detected first. If the hasura CLI binary is in PATH it is used directly (handles all YAML features). Otherwise nSelf resolves !include directives in Go and sends the result to the metadata API.
JSON format (legacy nSelf): projectDir/hasura/metadata.json Sent directly to the replace_metadata API.
If neither exists, reload_metadata is called (safe/idempotent).
func HasuraDiffMetadata ¶ added in v1.0.6
func HasuraDiffMetadata(ctx context.Context, cfg *config.Config, projectDir string) ([]string, error)
HasuraDiffMetadata compares live metadata against on-disk YAML files. Returns a list of keys that differ. Empty list means no drift.
func HasuraExportMetadata ¶
HasuraExportMetadata retrieves the current metadata from Hasura as raw JSON bytes.
func HasuraExportToYAML ¶ added in v1.0.6
HasuraExportToYAML exports live Hasura metadata to a git-friendly sorted YAML directory structure under {projectDir}/hasura/metadata/. Returns the output directory path.
func HasuraReloadMetadata ¶
HasuraReloadMetadata tells Hasura to reload its metadata from the internal catalog, picking up any changes to tracked tables, relationships, or permissions.
func HasuraValidatePermissions ¶ added in v1.0.6
HasuraValidatePermissions checks that every tenant-scoped table tracked by Hasura has permissions for tenant_member and tenant_admin roles. Returns a list of tables missing required permissions.
func InitializeDatabase ¶
InitializeDatabase waits for PostgreSQL to become ready, then creates the database, schemas, grants, and required extensions. This is Phase 3 of the nself startup sequence.
Steps:
- Wait for pg_isready (max 60s, check every 1s)
- CREATE DATABASE IF NOT EXISTS
- CREATE SCHEMA IF NOT EXISTS auth, storage, public
- GRANT ALL ON SCHEMA auth, storage, public TO user
- CREATE EXTENSION IF NOT EXISTS pgcrypto, citext
func MetadataSnapshot ¶ added in v1.0.9
MetadataSnapshot captures the current live metadata as a JSON snapshot. Useful for comparing before/after schema migrations.
func MigrateDown ¶
MigrateDown reverts the most recently applied migration. It looks for a corresponding .down.sql file next to the original migration.
func MigrateUp ¶
MigrateUp applies all pending migrations from the migrations directory. If plugin is non-empty, only that plugin's migrations are applied. Uses advisory locks to prevent concurrent runs, records SHA-256 checksums, and detects non-transactional statements (CREATE INDEX CONCURRENTLY) to run them outside a transaction. Returns the count of migrations applied.
func MigrateUpDir ¶ added in v1.1.1
MigrateUpDir applies all .sql files in the given directory in lexicographic order, skipping any already recorded in schema_versions (idempotent). This is the --migration-dir companion to ApplyFile (G-008).
func MustSanitizeIdentifier ¶ added in v1.0.9
MustSanitizeIdentifier is SanitizeIdentifier that panics on invalid input. Only use for compile-time-constant identifiers where validation is a sanity check, not a user-input boundary.
func Open ¶ added in v1.0.9
Open opens a database/sql connection to the project's PostgreSQL instance. The caller is responsible for calling db.Close() when done.
func PITRRestore ¶ added in v1.0.9
PITRRestore restores the database to a specific point in time using archived WALs. targetTime is in RFC3339 format (e.g. "2024-01-15T14:30:00Z").
func PendingMigrations ¶ added in v1.0.2
PendingMigrations returns the list of migration names that have not yet been applied.
func PgBouncerConfigFile ¶ added in v1.0.9
PgBouncerConfigFile generates the pgbouncer.ini content for a project. Returns the INI file contents as a string.
func PgBouncerConnectionURL ¶ added in v1.0.9
PgBouncerConnectionURL returns the connection URL that points through PgBouncer instead of directly to PostgreSQL.
func PgBouncerHBAFile ¶ added in v1.0.9
PgBouncerHBAFile generates the pg_hba.conf-style auth file content for PgBouncer.
func PgBouncerUserlistFile ¶ added in v1.0.9
PgBouncerUserlistFile generates the userlist.txt content for PgBouncer. Passwords are stored in plaintext here; PgBouncer supports md5 and plaintext.
func PruneRemoteBackups ¶ added in v1.0.9
func PruneRemoteBackups(ctx context.Context, cfg *config.Config, xrCfg CrossRegionBackupConfig) (pruned int, err error)
PruneRemoteBackups removes remote backups older than RetentionDays.
func RecordDrillResult ¶ added in v1.0.9
func RecordDrillResult(projectDir string, result RestoreDrillResult) error
RecordDrillResult appends the drill result to .nself/restore-drills.log in JSON format (one JSON object per line).
func ResetChecksum ¶ added in v1.0.6
ResetChecksum updates the stored checksum for a migration to match the current file on disk.
func Restore ¶
Restore streams a pg_dump custom-format file into the project's postgres container via pg_restore. The file contents are piped to docker exec's stdin, avoiding the need to copy the dump into the container first.
func SanitizeIdentifier ¶ added in v1.0.9
SanitizeIdentifier validates a SQL identifier and returns a double-quoted, escape-safe form suitable for direct interpolation into SQL. Returns an error if the input does not match the safe identifier pattern.
Use this for database names, schema names, table names, column names, and any other SQL identifier that must appear in a statement string. NEVER interpolate a raw string into SQL without validation.
func Seed ¶
Seed executes SQL seed files against the postgres database. If file is specified, only that file is run. If file is empty, all *.sql files in the seeds/ directory are executed in alphabetical order.
func SeedFilter ¶
SeedFilter returns the subset of seedFiles that should run in currentEnv. DB_ENV_SEEDS format: "dev:file1.sql,staging:file2.sql" Files not mentioned in dbEnvSeeds run in all environments. Files mentioned in dbEnvSeeds only run when their env matches currentEnv.
func SyncBackupToRemote ¶ added in v1.0.9
func SyncBackupToRemote(ctx context.Context, cfg *config.Config, xrCfg CrossRegionBackupConfig) error
SyncBackupToRemote syncs local backups to the remote location using rclone. Creates a local backup first if no recent backup exists (within 24h).
func TestWALArchive ¶ added in v1.0.9
TestWALArchive creates a test WAL file and verifies it is archived correctly. Returns an error if archiving fails or times out.
func VerifyRestoredDatabase ¶ added in v1.0.9
func VerifyRestoredDatabase(ctx context.Context, cfg *config.Config, drillDB string) (tables int, rows int64, err error)
VerifyRestoredDatabase connects to a restored database and runs basic integrity checks: counts rows in key tables, verifies pg_catalog consistency.
func WritePITRConfig ¶ added in v1.0.9
func WritePITRConfig(cfg *config.Config, projectDir string, pitrCfg PITRConfig) error
WritePITRConfig writes the PITR configuration to .nself/pitr/postgresql.conf.d/pitr.conf. This file should be mounted into the PostgreSQL container.
Types ¶
type ChecksumMismatch ¶ added in v1.0.6
type ChecksumMismatch struct {
ID string
Name string
Expected string // stored in DB
Actual string // computed from disk
}
ChecksumMismatch describes a migration whose on-disk checksum differs from the recorded value.
func VerifyChecksums ¶ added in v1.0.6
func VerifyChecksums(ctx context.Context, cfg *config.Config, plugin string) ([]ChecksumMismatch, error)
VerifyChecksums compares on-disk migration checksums against stored values. Returns a list of mismatches (empty means all good).
type CrossRegionBackupConfig ¶ added in v1.0.9
type CrossRegionBackupConfig struct {
Enabled bool
RemotePath string // rclone remote path (e.g. "s3:mybucket/backups")
SecondaryRegion string
Retention int // days to keep remote backups
Encrypted bool
AgeRecipients string
}
CrossRegionBackupConfig holds the configuration for cross-region backup.
type CrossRegionBackupStatus ¶ added in v1.0.9
type CrossRegionBackupStatus struct {
LastSync time.Time
FilesTransferred int
BytesTransferred int64
Errors []string
}
CrossRegionBackupStatus describes the last backup sync result.
func GetCrossRegionStatus ¶ added in v1.0.9
func GetCrossRegionStatus(ctx context.Context, cfg *config.Config, xrCfg CrossRegionBackupConfig) (CrossRegionBackupStatus, error)
GetCrossRegionStatus checks the rclone remote for recent backups.
type DriftSummary ¶ added in v1.0.9
type DriftSummary struct {
TotalTables int
CompliantTables int
DriftedTables int
MissingRequired int // tables missing at least one REQUIRED column
OverallScore int // 0-100
}
DriftSummary returns a high-level summary: total tables, compliant, drifted, score.
func SummarizeDrift ¶ added in v1.0.9
func SummarizeDrift(results []SchemaDriftResult) DriftSummary
SummarizeDrift returns a high-level summary across all drift results.
type DrillOptions ¶ added in v1.1.0
type DrillOptions struct {
// BackupFile, when set, drills against a specific backup. Empty = most recent.
BackupFile string
// RTOTargetHours is the failure threshold for total drill wall-clock.
// Default 4 hours per STRAT-11. Setting <= 0 disables the gate (the drill
// still runs and reports duration; result.RTOTargetMet stays true).
RTOTargetHours float64
// DryRun, when true, validates the inputs and prints what would happen
// without actually creating the scratch DB or touching pg_restore.
DryRun bool
// ProjectDir is where .nself/drill-log.json lives. Defaults to ".".
ProjectDir string
}
DrillOptions captures the user-facing knobs for `nself backup drill`. All fields are optional; sensible defaults come from the project config.
type DrillResult ¶ added in v1.1.0
type DrillResult struct {
StartedAt time.Time `json:"started_at"`
CompletedAt time.Time `json:"completed_at"`
BackupFile string `json:"backup_file"`
Success bool `json:"success"`
Phase string `json:"phase,omitempty"` // last phase reached (init|restore|verify|smoke|done|dry-run)
ErrorMessage string `json:"error_message,omitempty"`
TotalDuration time.Duration `json:"total_duration_ns"`
RestoreSeconds float64 `json:"restore_seconds"`
VerifySeconds float64 `json:"verify_seconds"`
SmokeSeconds float64 `json:"smoke_seconds"`
TablesChecked int `json:"tables_checked"`
RowsObserved int64 `json:"rows_observed"`
RTOTargetMet bool `json:"rto_target_met"`
}
DrillResult is the structured outcome of a single `nself backup drill` run. Phase timings are zero when a phase did not execute. All fields serialize to JSON for the drill log + doctor consumption.
func Drill ¶ added in v1.1.0
func Drill(ctx context.Context, cfg *config.Config, opts DrillOptions) (DrillResult, error)
Drill runs the high-level drill orchestration: invokes RestoreDrill for the heavy lifting, layers RTO measurement + smoke checks on top, and emits a structured DrillResult to .nself/drill-log.json. The function never returns nil result — even on early failure the result captures whatever timing data was collected up to the failure point.
func LastSuccessfulDrill ¶ added in v1.1.0
func LastSuccessfulDrill(projectDir string) (DrillResult, bool)
LastSuccessfulDrill returns the most recent successful DrillResult from the drill log, or (zero, false) when no successful drill has run yet. The doctor check OPS-DRILL-01 calls this to enforce "drill within last 7 days".
type FKIndexInfo ¶ added in v1.0.9
type FKIndexInfo struct {
TableSchema string
TableName string
ColumnName string
ForeignSchema string
ForeignTable string
ForeignColumn string
HasIndex bool
ConstraintName string
}
FKIndexInfo describes a foreign key constraint and whether it has an index.
func AuditFKIndexes ¶ added in v1.0.9
AuditFKIndexes finds all foreign key columns and reports whether each has a supporting index. Only tables in np_* and public schemas are checked.
type HasuraGitStatus ¶ added in v1.0.9
type HasuraGitStatus struct {
Branch string
CommitHash string
LastExportAt time.Time
Modified []string // metadata files with uncommitted changes
IsClean bool
}
HasuraGitStatus describes the git state of metadata files.
func GetGitStatus ¶ added in v1.0.9
func GetGitStatus(projectDir string) (HasuraGitStatus, error)
GetGitStatus returns the git status of the hasura/metadata/ directory.
type MetadataDrift ¶ added in v1.0.9
type MetadataDrift struct {
// TablesAdded are tracked tables in live Hasura not in committed metadata.
TablesAdded []string
// TablesRemoved are tables in committed metadata not in live Hasura.
TablesRemoved []string
// PermissionsChanged are tables where permissions differ.
PermissionsChanged []string
// RelationshipsChanged are tables where relationships differ.
RelationshipsChanged []string
// IsClean is true when live matches committed exactly.
IsClean bool
}
MetadataDrift describes the difference between live Hasura metadata and committed files.
func DetectMetadataDrift ¶ added in v1.0.9
func DetectMetadataDrift(ctx context.Context, cfg *config.Config, projectDir string) (MetadataDrift, error)
DetectMetadataDrift compares live Hasura metadata against committed files in hasura/metadata/. It exports current metadata via the Hasura API and diffs against the on-disk files.
type MigrationAuditResult ¶ added in v1.0.9
type MigrationAuditResult struct {
Name string
Applied bool
Idempotent bool // uses IF NOT EXISTS, IF EXISTS, CREATE OR REPLACE
HasRollback bool // a down.sql exists alongside up.sql
ChecksumMatch bool // file checksum matches stored checksum in nself_ops.migrations
Issues []string // list of idempotency problems found
}
MigrationAuditResult describes the audit result for a single migration.
func AuditMigrations ¶ added in v1.0.9
AuditMigrations audits all migration files for idempotency and drift. It checks:
- All applied migrations have matching checksums (no file edits after apply)
- Pending migrations use idempotent SQL patterns (IF NOT EXISTS, etc.)
- Each migration has a corresponding down/rollback file
type MigrationRecord ¶ added in v1.0.6
type MigrationRecord struct {
ID string
Name string
Checksum string
AppliedAt string
AppliedBy string
DurationMs int
RolledBack bool
}
MigrationRecord holds the state of a migration from nself_ops.migrations.
type MigrationStatus ¶
MigrationStatus describes the state of a single migration file.
func MigrateStatus ¶
MigrateStatus returns the status of all known migrations (applied and pending). It merges on-disk migration files with the schema_versions table, so orphaned migrations (applied but no longer on disk) are also reported.
type PITRConfig ¶ added in v1.0.9
type PITRConfig struct {
ArchiveDir string
WalInterval int
RemotePath string // rclone remote path for WAL shipping
}
PITRConfig holds the generated PostgreSQL settings for PITR.
type PITRStatus ¶ added in v1.0.9
type PITRStatus struct {
ArchiveMode string // on, off, always
ArchiveCommand string
WALLevel string // replica, logical
MaxWALSenders int
WALArchiveDir string
LastArchivedWAL string
LastArchiveTime string
ArchiveEnabled bool
}
PITRStatus describes the current PITR configuration state.
func GetPITRStatus ¶ added in v1.0.9
GetPITRStatus queries PostgreSQL for current WAL archiving settings.
type PgBouncerStatus ¶ added in v1.0.9
type PgBouncerStatus struct {
Running bool
PoolMode string
ActivePools int
IdleServers int
ActiveClients int
}
PgBouncerStatus holds runtime status of PgBouncer.
func GetPgBouncerStatus ¶ added in v1.0.9
GetPgBouncerStatus queries the PgBouncer admin database for runtime status. It connects via psql inside the pgbouncer container (named {project}_pgbouncer).
type RLSTableInfo ¶ added in v1.0.9
type RLSTableInfo struct {
TableSchema string `json:"table_schema"`
TableName string `json:"table_name"`
RLSEnabled bool `json:"rls_enabled"`
ForceRLS bool `json:"force_rls"`
PolicyCount int `json:"policy_count"`
}
RLSTableInfo holds the RLS state for a single table returned by AuditRLS.
type RequiredColumn ¶ added in v1.0.9
type RequiredColumn struct {
Name string
DataType string
Required bool // if false, column is recommended but not required
Description string
}
RequiredColumn defines a column that should exist on all np_* tables.
type RestoreDrillResult ¶ added in v1.0.9
type RestoreDrillResult struct {
StartedAt time.Time `json:"started_at"`
CompletedAt time.Time `json:"completed_at"`
BackupFile string `json:"backup_file"`
Success bool `json:"success"`
TablesVerified int `json:"tables_verified"`
RowsVerified int64 `json:"rows_verified"`
ErrorMessage string `json:"error_message,omitempty"`
Duration time.Duration `json:"duration_ns"`
}
RestoreDrillResult describes the outcome of a restore test.
func RestoreDrill ¶ added in v1.0.9
func RestoreDrill(ctx context.Context, cfg *config.Config, backupFile string) (RestoreDrillResult, error)
RestoreDrill runs a restore drill using the most recent backup. It restores to a TEMPORARY database named {dbname}_drilltest, verifies data integrity, then drops the temporary database. This is non-destructive — it does not touch the production database.
type SchemaDriftResult ¶ added in v1.0.9
type SchemaDriftResult struct {
TableSchema string
TableName string
MissingColumns []RequiredColumn
PresentColumns []string
DriftScore int // 0-100, higher = more drift
}
SchemaDriftResult describes drift for a single table.
func ScanSchemaDrift ¶ added in v1.0.9
ScanSchemaDrift scans all np_* tables for the 5 required Theme 25 columns. Only tables in schemas starting with "np_" are checked.
type SoftDeleteInfo ¶ added in v1.0.9
type SoftDeleteInfo struct {
TableSchema string
TableName string
HasDeletedAt bool
HasIndex bool // index on deleted_at for performance
HasView bool // {table}_active view exists
}
SoftDeleteInfo describes a table's soft-delete status.
func AuditSoftDelete ¶ added in v1.0.9
AuditSoftDelete scans tables in schemas starting with "np_" or "public" and reports their soft-delete status.
type TenantRLSConfig ¶ added in v1.0.9
type TenantRLSConfig struct {
Pattern TenantRLSPattern
Schema string
Table string
UserColumn string // column compared to hasura.user (default: "user_id")
TenantColumn string // column compared to hasura.tenant (default: "tenant_id")
}
TenantRLSConfig specifies the parameters needed to generate and apply RLS policies for a single table.
type TenantRLSPattern ¶ added in v1.0.9
type TenantRLSPattern string
TenantRLSPattern describes the access-control model for a table.
const ( // PatternUserOwned restricts access to rows whose user_id matches the // Hasura session variable hasura.user. Admins bypass via hasura.role. PatternUserOwned TenantRLSPattern = "user_owned" // PatternTenantScoped restricts access to rows whose tenant_id matches the // Hasura session variable hasura.tenant. Admins bypass via hasura.role. PatternTenantScoped TenantRLSPattern = "tenant_scoped" // PatternPublic makes every row visible to all sessions without restriction. PatternPublic TenantRLSPattern = "public" // PatternAdminOnly restricts all access to sessions where hasura.role = 'admin'. PatternAdminOnly TenantRLSPattern = "admin_only" )