doctor

package
v1.0.11 Latest Latest
Warning

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

Go to latest
Published: Apr 24, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

S77-T08: doctor --deep check for orphaned Hasura remote schemas.

A remote schema is "orphaned" when it is registered in Hasura metadata but the plugin that provides it is no longer installed. This can happen after `nself plugin uninstall <name>` if Hasura metadata was not cleaned up, or after a manual plugin removal. Orphaned remote schemas cause Hasura to emit schema-load errors on startup and break the GraphQL API surface.

Detection strategy:

  1. Read NSELF_HASURA_GRAPHQL_URL (or derive from HASURA_GRAPHQL_URL) to locate the running Hasura instance.
  2. Call the Hasura Metadata API to export remote_schemas (POST /v1/metadata with {"type":"export_metadata","args":{}}). Requires HASURA_GRAPHQL_ADMIN_SECRET.
  3. For each remote schema entry, derive the expected plugin name from the remote schema's URL: internal plugin URLs follow the pattern http://host:PORT where PORT is registered in PLUGIN_<NAME>_INTERNAL_URL.
  4. Cross-reference against loaded plugins: env var NSELF_PLUGINS_LOADED (comma- separated list set by `nself build`) and per-plugin PLUGIN_<NAME>_INTERNAL_URL.
  5. Emit WARN for each orphan found; PASS if none; SKIP if Hasura is unreachable.

The check is read-only — it never modifies Hasura metadata. S77-T08

S69-T05: doctor check for ai+moderation wiring on public-bound deployments.

If the ai plugin is loaded AND the deployment binding is non-loopback AND the moderation plugin is NOT loaded, this emits a WARN. Severity is WARN (not FAIL) because self-hosted single-user setups are legitimate.

Package doctor provides comprehensive health check sections for nself doctor.

Index

Constants

View Source
const (
	// DefaultPostgresMaxConnections is the Postgres default max_connections setting.
	// Operators should raise this in POSTGRES_MAX_CONNECTIONS when running many services.
	DefaultPostgresMaxConnections = 100

	// PoolCapCheckID is the canonical check ID referenced in docs and Alertmanager.
	PoolCapCheckID = "PERF-POOL-01"
)
View Source
const (
	// RLSCheckID is the canonical check ID referenced in docs, wiki, and Alertmanager.
	RLSCheckID = "PERM-RLS-01"
)

Variables

This section is empty.

Functions

func RecommendedPoolSize added in v1.0.11

func RecommendedPoolSize(postgresMaxConnections, numServices int) int

RecommendedPoolSize computes the recommended per-service MaxConns cap.

MaxConns = min(10, floor(postgres_max_connections / num_services))

Edge cases:

  • numServices=0 → returns 10 (no services, no constraint)
  • very large max_connections → capped at 10 (prevents runaway allocations)
  • numServices > max_connections → returns 1 (absolute minimum)

Types

type CheckResult

type CheckResult struct {
	Section string `json:"section"`
	Name    string `json:"name"`
	Status  string `json:"status"` // pass, warn, fail
	Message string `json:"message"`
	FixCmd  string `json:"fix_cmd,omitempty"` // suggested fix command
}

CheckResult holds the outcome of a single diagnostic check.

func BackupChecks

func BackupChecks(_ context.Context, projectDir string) []CheckResult

BackupChecks verifies backup health.

func CheckAdminBind added in v1.0.11

func CheckAdminBind(ctx context.Context) CheckResult

CheckAdminBind verifies that the nself-admin container is bound to 127.0.0.1 only (not 0.0.0.0 which would expose it to the LAN). This implements S43-T03 — required by the Service Binding Hard Rule.

func CheckEncryptionKeyScope added in v1.0.11

func CheckEncryptionKeyScope(projectDir string, strict bool) []CheckResult

CheckEncryptionKeyScope verifies that AI_ENCRYPTION_KEY (and any other *_ENCRYPTION_KEY env vars) are set and are not reused across environments. Implements S43-UNDEP-01 + S43-AUDIT-01 (SEC-ENC-01 and SEC-ENC-02).

When strict=true, a shared or default key returns Status="fail". When strict=false (default), it returns Status="warn" — allowing the admin to investigate without blocking a deploy.

func CheckHasuraIntrospection added in v1.0.11

func CheckHasuraIntrospection(_ context.Context) CheckResult

CheckHasuraIntrospection implements SEC-HASURA-INTRO-01. It warns if HASURA_GRAPHQL_DISABLE_INTROSPECTION is not set to "true" in a production environment (NSELF_ENV=production or NODE_ENV=production).

The check is:

  • status "skip": environment is dev/staging or NSELF_ENV is unset/empty
  • status "pass": HASURA_GRAPHQL_DISABLE_INTROSPECTION=true in production
  • status "warn": HASURA_GRAPHQL_DISABLE_INTROSPECTION absent or not "true" in production

The check is read-only — it never modifies Hasura configuration. S70-T06

func CheckJWTSecretPresent added in v1.0.7

func CheckJWTSecretPresent(projectDir string) CheckResult

CheckJWTSecretPresent reports whether HASURA_GRAPHQL_JWT_SECRET is defined in any of the project's env files. Semantics:

  • fail when the key is absent from both .env and .env.secrets and no other env file has it either; this is what the spec calls "Hasura enabled but JWT secret absent from both sources".
  • warn when the key is in .env.secrets but missing from .env. This is the nSelf-preferred arrangement (secrets live in .env.secrets which is gitignored and chmod 0600), so it is informational only.
  • pass when the key is present in .env (with or without .env.secrets).

projectDir is the working directory passed through from `nself doctor`.

func CheckModerationWired added in v1.0.11

func CheckModerationWired(_ context.Context) CheckResult

CheckModerationWired implements S69-T05: warns when the ai plugin is loaded on a public-bound deployment without the moderation plugin also loaded.

Detection logic:

  • ai plugin loaded: NSELF_AI_LOADED=1 OR PLUGIN_AI_INTERNAL_URL non-empty
  • moderation plugin loaded: NSELF_MODERATION_LOADED=1 OR PLUGIN_MODERATION_INTERNAL_URL non-empty
  • public bind: NSELF_BIND_ADDRESS is NOT 127.x / localhost / ::1 / "" (empty = loopback default)

func CheckOrphanRemoteSchemas added in v1.0.11

func CheckOrphanRemoteSchemas(ctx context.Context) CheckResult

CheckOrphanRemoteSchemas implements S77-T08. It queries Hasura metadata and compares registered remote schemas against the currently installed nself plugins. Any remote schema whose providing plugin is absent is flagged as an orphan.

func CheckRLSEnforcement added in v1.0.11

func CheckRLSEnforcement(ctx context.Context, strict bool) []CheckResult

CheckRLSEnforcement implements PERM-RLS-01.

It queries Postgres pg_class for every np_* table and verifies:

(a) RLS is enabled (relrowsecurity = true)
(b) at least one policy exists
(c) PatternTenantScoped tables have FORCE RLS (relforcerowsecurity = true)
(d) tables with tenant_id column have Hasura row filter for that column

Violations are WARN by default. Pass strict=true to escalate to fail.

This check is read-only. It never modifies DB state.

func DeepChecks

func DeepChecks(ctx context.Context, projectDir string, verbose bool) []CheckResult

DeepChecks runs all 12 subsystem categories for --deep mode.

func DockerDeepChecks

func DockerDeepChecks(ctx context.Context, verbose bool) []CheckResult

DockerDeepChecks verifies daemon, storage driver, dangling images, container health.

func FilterBySection

func FilterBySection(results []CheckResult, section string) []CheckResult

FilterBySection returns only checks matching the given section name.

func FixItEngine

func FixItEngine(ctx context.Context, results []CheckResult) []CheckResult

FixItEngine runs safe auto-fixes for check results that have FixCmd set.

func HasuraChecks

func HasuraChecks(ctx context.Context, verbose bool) []CheckResult

HasuraChecks verifies /healthz 200 and metadata consistency.

func HostChecks

func HostChecks(ctx context.Context, verbose bool) []CheckResult

HostChecks verifies disk, memory, CPU, time sync, kernel.

func LicenseChecks

func LicenseChecks(ctx context.Context, projectDir string, verbose bool) []CheckResult

LicenseChecks verifies license is current and tier matches expected.

func MonitoringChecks

func MonitoringChecks(ctx context.Context) []CheckResult

MonitoringChecks verifies monitoring stack health.

func NginxChecks

func NginxChecks(ctx context.Context, verbose bool) []CheckResult

NginxChecks verifies config test and SSL cert expiry.

func PingChecks

func PingChecks(ctx context.Context, verbose bool) []CheckResult

PingChecks verifies ping.nself.org reachable and license cache fresh.

func PluginHealthChecks

func PluginHealthChecks(ctx context.Context, projectDir string, verbose bool) []CheckResult

PluginHealthChecks verifies every installed plugin's health endpoint.

func PoolCapacityCheck added in v1.0.11

func PoolCapacityCheck(_ context.Context, pools []PoolConfig, postgresMaxConnections int) CheckResult

PoolCapacityCheck verifies that the total configured pgxpool connections across all active services do not exceed postgres_max_connections.

Returns a CheckResult with:

  • Status "pass" when total_conns ≤ postgres_max_connections
  • Status "warn" when total_conns > postgres_max_connections (not a hard block)
  • Status "fail" when inputs are invalid (zero services, negative max)

This check fires in nself doctor --deep as PERF-POOL-01.

func PostgresChecks

func PostgresChecks(ctx context.Context, verbose bool) []CheckResult

PostgresChecks verifies pg_isready, replication lag, longest query, dead tuples, vacuum.

func SSLChecks

func SSLChecks(ctx context.Context, verbose bool) []CheckResult

SSLChecks verifies LE renewal cron, last renewal, OCSP stapling.

func SecurityChecks

func SecurityChecks(ctx context.Context, projectDir string) []CheckResult

SecurityChecks runs security diagnostics.

func SystemChecks

func SystemChecks(ctx context.Context, verbose bool) []CheckResult

SystemChecks runs system-level diagnostics: disk, memory, swap, load, clock sync, Docker, kernel.

type PoolConfig added in v1.0.11

type PoolConfig struct {
	ServiceName string
	MaxConns    int // per-service pgxpool MaxConns (0 = use pgxpoolDefaultMaxConns)
}

PoolConfig describes the pool sizing input for a single service. Each plugin or required service exposes one pool config.

func DefaultPoolConfigs added in v1.0.11

func DefaultPoolConfigs(services []string) []PoolConfig

DefaultPoolConfigs returns a pool config slice for the standard nSelf service set (4 required + up to 7 optional). Pass only the enabled services. Used by nself doctor --deep to compute the PERF-POOL-01 check.

Jump to

Keyboard shortcuts

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