database

package
v1.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 15, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package database — drill.go: high-level DR drill orchestration.

S9.T03 + S9.T15-T16 (P100 v1.1.0): The `nself backup drill` command wraps the existing RestoreDrill primitive (restore_drill.go) with three production concerns the bare drill primitive does not address:

  1. 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.
  2. 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.
  3. 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

Constants

This section is empty.

Variables

View Source
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).

View Source
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

func ApplyDefaultRLSPolicies(ctx context.Context, cfg *config.Config, schema, table string) error

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

func ApplyDir(ctx context.Context, cfg *config.Config, dirPath string) (int, error)

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

func ApplyFile(ctx context.Context, cfg *config.Config, filePath string) (skipped bool, err error)

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

func ApplySoftDelete(ctx context.Context, cfg *config.Config, schema, table string) error

ApplySoftDelete runs the soft-delete migration for a specific table.

func ApplyTenantRLS added in v1.0.9

func ApplyTenantRLS(ctx context.Context, dbcfg *config.Config, rlsCfg TenantRLSConfig) error

ApplyTenantRLS generates the RLS SQL for the given TenantRLSConfig and pipes it to the postgres container via psql.

func Backup

func Backup(ctx context.Context, cfg *config.Config, outputPath string) error

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

func CheckMigrationIdempotency(sqlContent string) (bool, []string)

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

func CompareSnapshots(before, after []byte) (string, error)

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

func EnableRLSOnTable(ctx context.Context, cfg *config.Config, schema, table string) error

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

func GenerateIdempotentVersion(sqlContent string) (converted string, changes []string)

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

func GenerateRollbackSQL(schema, table string) string

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

func GenerateSoftDeleteMigration(schema, table string) (upSQL, downSQL string)

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

func GenerateTrackTableSQL(schema, table string) string

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

func HasuraApplyMetadata(ctx context.Context, cfg *config.Config, projectDir string) error

HasuraApplyMetadata applies Hasura metadata from projectDir.

It supports two metadata formats:

  1. 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.

  2. 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

func HasuraExportMetadata(ctx context.Context, cfg *config.Config) ([]byte, error)

HasuraExportMetadata retrieves the current metadata from Hasura as raw JSON bytes.

func HasuraExportToYAML added in v1.0.6

func HasuraExportToYAML(ctx context.Context, cfg *config.Config, projectDir string) (string, error)

HasuraExportToYAML exports live Hasura metadata to a git-friendly sorted YAML directory structure under {projectDir}/hasura/metadata/. Returns the output directory path.

func HasuraReloadMetadata

func HasuraReloadMetadata(ctx context.Context, cfg *config.Config) error

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

func HasuraValidatePermissions(ctx context.Context, cfg *config.Config) ([]string, error)

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

func InitializeDatabase(ctx context.Context, cfg *config.Config) error

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:

  1. Wait for pg_isready (max 60s, check every 1s)
  2. CREATE DATABASE IF NOT EXISTS
  3. CREATE SCHEMA IF NOT EXISTS auth, storage, public
  4. GRANT ALL ON SCHEMA auth, storage, public TO user
  5. CREATE EXTENSION IF NOT EXISTS pgcrypto, citext

func MetadataSnapshot added in v1.0.9

func MetadataSnapshot(ctx context.Context, cfg *config.Config) ([]byte, error)

MetadataSnapshot captures the current live metadata as a JSON snapshot. Useful for comparing before/after schema migrations.

func MigrateDown

func MigrateDown(ctx context.Context, cfg *config.Config) error

MigrateDown reverts the most recently applied migration. It looks for a corresponding .down.sql file next to the original migration.

func MigrateUp

func MigrateUp(ctx context.Context, cfg *config.Config, plugin string) (int, error)

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

func MigrateUpDir(ctx context.Context, cfg *config.Config, dir string) (int, error)

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

func MustSanitizeIdentifier(s string) string

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

func Open(ctx context.Context, cfg *config.Config) (*sql.DB, error)

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

func PITRRestore(ctx context.Context, cfg *config.Config, targetTime string) error

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

func PendingMigrations(ctx context.Context, cfg *config.Config, plugin string) ([]string, error)

PendingMigrations returns the list of migration names that have not yet been applied.

func PgBouncerConfigFile added in v1.0.9

func PgBouncerConfigFile(cfg *config.Config) string

PgBouncerConfigFile generates the pgbouncer.ini content for a project. Returns the INI file contents as a string.

func PgBouncerConnectionURL added in v1.0.9

func PgBouncerConnectionURL(cfg *config.Config) string

PgBouncerConnectionURL returns the connection URL that points through PgBouncer instead of directly to PostgreSQL.

func PgBouncerHBAFile added in v1.0.9

func PgBouncerHBAFile(cfg *config.Config) string

PgBouncerHBAFile generates the pg_hba.conf-style auth file content for PgBouncer.

func PgBouncerUserlistFile added in v1.0.9

func PgBouncerUserlistFile(cfg *config.Config) string

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

func ResetChecksum(ctx context.Context, cfg *config.Config, migrationID string) error

ResetChecksum updates the stored checksum for a migration to match the current file on disk.

func Restore

func Restore(ctx context.Context, cfg *config.Config, inputPath string) error

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

func SanitizeIdentifier(s string) (string, error)

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

func Seed(ctx context.Context, cfg *config.Config, file string) error

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

func SeedFilter(seedFiles []string, dbEnvSeeds string, currentEnv string) []string

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

func TestWALArchive(ctx context.Context, cfg *config.Config) error

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.

func WritePgBouncerConfig added in v1.0.9

func WritePgBouncerConfig(ctx context.Context, cfg *config.Config, projectDir string) error

WritePgBouncerConfig writes the three PgBouncer config files to the project's .nself/pgbouncer/ directory.

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

func AuditFKIndexes(ctx context.Context, cfg *config.Config) ([]FKIndexInfo, error)

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

func AuditMigrations(ctx context.Context, cfg *config.Config) ([]MigrationAuditResult, error)

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

type MigrationStatus struct {
	Name      string
	Applied   bool
	Timestamp time.Time
}

MigrationStatus describes the state of a single migration file.

func MigrateStatus

func MigrateStatus(ctx context.Context, cfg *config.Config) ([]MigrationStatus, error)

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

func GetPITRStatus(ctx context.Context, cfg *config.Config) (PITRStatus, error)

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

func GetPgBouncerStatus(ctx context.Context, cfg *config.Config) (*PgBouncerStatus, error)

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.

func AuditRLS added in v1.0.9

func AuditRLS(ctx context.Context, cfg *config.Config) ([]RLSTableInfo, error)

AuditRLS queries pg_catalog.pg_class and pg_policies to return the RLS state for every table in schemas starting with "np_" or in schema "public". It identifies tables that are missing RLS or have zero policies.

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

func ScanSchemaDrift(ctx context.Context, cfg *config.Config) ([]SchemaDriftResult, error)

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

func AuditSoftDelete(ctx context.Context, cfg *config.Config) ([]SoftDeleteInfo, error)

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"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL