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:
- Read NSELF_HASURA_GRAPHQL_URL (or derive from HASURA_GRAPHQL_URL) to locate the running Hasura instance.
- Call the Hasura Metadata API to export remote_schemas (POST /v1/metadata with {"type":"export_metadata","args":{}}). Requires HASURA_GRAPHQL_ADMIN_SECRET.
- 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.
- Cross-reference against loaded plugins: env var NSELF_PLUGINS_LOADED (comma- separated list set by `nself build`) and per-plugin PLUGIN_<NAME>_INTERNAL_URL.
- 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
- func RecommendedPoolSize(postgresMaxConnections, numServices int) int
- type CheckResult
- func BackupChecks(_ context.Context, projectDir string) []CheckResult
- func CheckAdminBind(ctx context.Context) CheckResult
- func CheckEncryptionKeyScope(projectDir string, strict bool) []CheckResult
- func CheckHasuraIntrospection(_ context.Context) CheckResult
- func CheckJWTSecretPresent(projectDir string) CheckResult
- func CheckModerationWired(_ context.Context) CheckResult
- func CheckOrphanRemoteSchemas(ctx context.Context) CheckResult
- func CheckRLSEnforcement(ctx context.Context, strict bool) []CheckResult
- func DeepChecks(ctx context.Context, projectDir string, verbose bool) []CheckResult
- func DockerDeepChecks(ctx context.Context, verbose bool) []CheckResult
- func FilterBySection(results []CheckResult, section string) []CheckResult
- func FixItEngine(ctx context.Context, results []CheckResult) []CheckResult
- func HasuraChecks(ctx context.Context, verbose bool) []CheckResult
- func HostChecks(ctx context.Context, verbose bool) []CheckResult
- func LicenseChecks(ctx context.Context, projectDir string, verbose bool) []CheckResult
- func MonitoringChecks(ctx context.Context) []CheckResult
- func NginxChecks(ctx context.Context, verbose bool) []CheckResult
- func PingChecks(ctx context.Context, verbose bool) []CheckResult
- func PluginHealthChecks(ctx context.Context, projectDir string, verbose bool) []CheckResult
- func PoolCapacityCheck(_ context.Context, pools []PoolConfig, postgresMaxConnections int) CheckResult
- func PostgresChecks(ctx context.Context, verbose bool) []CheckResult
- func SSLChecks(ctx context.Context, verbose bool) []CheckResult
- func SecurityChecks(ctx context.Context, projectDir string) []CheckResult
- func SystemChecks(ctx context.Context, verbose bool) []CheckResult
- type PoolConfig
Constants ¶
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" )
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
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.