Skip to content

fix(build): P0 batch — manifest plugin injection, secret templating, env allowlist, localhost URLs, leftover cleanup#168

Merged
acamarata merged 5 commits into
mainfrom
fix/build-critical-p0-batch
Jul 3, 2026
Merged

fix(build): P0 batch — manifest plugin injection, secret templating, env allowlist, localhost URLs, leftover cleanup#168
acamarata merged 5 commits into
mainfrom
fix/build-critical-p0-batch

Conversation

@acamarata

Copy link
Copy Markdown
Collaborator

Fixes five dogfood-reported build/start bugs that break the simple self-host setup and the Sentry bundle install path.

Fixes

  1. CRITICAL — plugin injection dropped (51be7bf9): nself build ignored nself.yaml entirely; declared plugins/bundles never materialized and were silently dropped. New internal/build/manifest.go parses plugins:/bundle:/bundles:, expands bundles via the canonical catalog, best-effort auto-installs missing plugins (disable: NSELF_AUTO_INSTALL_PLUGINS=false), and reports any unwired plugin via loud per-plugin warnings + BuildResult.MissingPlugins + a printed fix command. Repro test: N declared → N wired.
  2. HIGH — secret templating (f6fef60a): literal secrets (Postgres password, Hasura admin secret, JWT blobs, MinIO creds) were baked into generated docker-compose.yml. Now emitted as ${VAR} refs; interpolation values written to .nself/compose.env (0600) and passed via --env-file. Test asserts zero literal secrets in generated compose.
  3. MED — env allowlist (54c469b6): app-owned vars (NODE_ENV, JWT_SECRET, LOG_LEVEL, ...) no longer warn; ENV_ALLOWLIST (exact names + PREFIX_*) for project passthrough.
  4. MED — localhost URLs (06d93be9): nself start prints reachable localhost:<port> endpoints for default local domains instead of unreachable *.local.nself.org; custom domains unchanged.
  5. LOW — hash-prefixed leftovers (a8210b33): pre/post-start cleanup removes interrupted-recreate rename leftovers (b6d7b59a1c78_<app>_hasura) that shadow clean container names.

Verification

  • go build ./..., go vet ./..., gofmt clean on touched files; 32 new tests green.
  • Real nself build in a temp project declaring bundle: nsentry + 2 free plugins: all 15 declared plugins wired into compose-files.txt; missing-plugin path warns loudly per plugin with exact fix command; generated docker-compose.yml contains zero literal secret values, only ${VAR} refs; .nself/compose.env written 0600.

PCIs: plugin-injection-dropped · compose-secret-templating · ntask-dev-env-schema-warnings · ntask-local-url-mismatch · ntask-hasura-container-hash-name

acamarata added 5 commits July 3, 2026 11:14
…ever silently drop

nself build ignored the project manifest entirely: plugins declared under
plugins:/bundle:/bundles: in nself.yaml never materialized as containers
because the only injection path was DiscoverPluginComposeFiles over
~/.nself/plugins (install-then-discover). Declaring a bundle in config
produced a stack with zero of its plugins and no warning.

- internal/build/manifest.go: nself.yaml reader (flat + free/pro plugin
  lists, bundle/bundles expansion via the canonical bundle catalog),
  ResolveDeclaredPlugins with best-effort auto-install (60s timeout,
  NSELF_AUTO_INSTALL_PLUGINS=false to disable) and core-service
  satisfaction (auth/storage)
- orchestrator: resolve declared plugins before nginx route injection,
  np_plugins seed, and compose discovery; report unwired plugins via
  slog warnings + BuildResult.MissingPlugins
- cmd/build: print loud warning with exact fix command when any declared
  plugin is not wired
- DefaultPluginDir: NSELF_PLUGIN_DIR env override (hermetic tests, CI,
  per-project plugin sets)
- tests: N-declared→N-wired repro, missing-plugin report, core-service
  aliases, placeholder filtering, no-manifest no-op

PCI: plugin-injection-dropped (ntask dogfood gap #8)
nself build baked literal secrets (POSTGRES_PASSWORD, Hasura admin
secret, JWT blobs, MinIO root creds, SMTP pass, ...) into the generated
docker-compose.yml. Editing .env was a silent no-op post-build, and any
commit of the generated file leaked credentials (ntask incident
085af2ec; ASI generated-file-secret hard rule).

- internal/build/secrets_template.go: SecretEnvMap + TemplateSecrets
  (exact env-key lines -> ${VAR}; alias keys AUTH_JWT_SECRET/
  AUTH_DB_PASSWORD value-checked; URL credential positions ':pw@' ->
  ':${VAR}@' only when no percent-encoding needed) + LiteralSecretLeaks
  safety-net warning
- orchestrator Step 8.7 applies templating before write; Step 10.1
  writes .nself/compose.env (0600) with all interpolation values
  (secrets + console/dev toggles + DATABASE_URL/DOCKER_NETWORK +
  plugin env vars)
- internal/docker: Compose.EnvFiles -> --env-file flags
- start/stop/restart/health pass build.ComposeEnvFiles(workdir);
  legacy projects without compose.env keep default .env discovery
- tests: real-generator repro (zero literal secrets, refs present),
  alias no-clobber, escaped-password guard, 0600 perms, flag order

PCI: compose-secret-templating
nself build warned 'unknown env var' for app-owned vars in real app
.env files (NODE_ENV, JWT_SECRET, SSL_AUTO_TRUST, COOKIE_SECRET,
ENABLE_DEBUG, LOG_LEVEL, NSELF_PROJECT_NAME — ntask dogfood gap #19).

- add the seven app-owned vars to knownEnvVars
- add ENV_ALLOWLIST: comma-separated exact names or prefix patterns
  ending in * (ENV_ALLOWLIST=MY_APP_TOKEN,FEATURE_*) that
  warnUnknownEnvVars skips — the documented mechanism for
  project-specific passthrough vars

PCI: ntask-dev-env-schema-warnings
nself start printed http://task.local.nself.org-style ready URLs that
require undocumented DNS/hosts/mkcert setup and 502 on a fresh machine,
while every app doc says http://localhost:<port> (ntask dogfood gap #20).

- cmd/commands/start_urls.go: stackURLs(cfg) — default local domains
  (empty/localhost/local.nself.org) print direct localhost:<port>
  endpoints (GraphQL, Hasura, Auth, Storage, Mail UI, Admin) plus a
  'requires: nself dns-setup' hint for the *.local.nself.org routes;
  custom domains keep nginx-routed URLs unchanged
- tests: local-domain repro, custom-domain regression, port fallbacks

PCI: ntask-local-url-mismatch
Interrupted docker compose recreates leave the old container renamed
with a hex-id prefix (b6d7b59a1c78_ntask_hasura). The leftover holds
ports and shadows the clean <project>_<service> name that app Makefiles
and docs rely on (docker exec ntask_hasura — ntask dogfood gap #21).

- internal/docker: isRenamedComposeLeftover matcher +
  cleanupRenamedLeftovers (docker ps -a scan, best-effort rm -f)
- RunPreStartCleanup before compose up; also appended to
  RunPostStartCleanup
- tests: matcher table (clean names, other projects, short-hex guards)

PCI: ntask-hasura-container-hash-name
@acamarata acamarata merged commit 5c33a18 into main Jul 3, 2026
28 of 33 checks passed
acamarata added a commit that referenced this pull request Jul 3, 2026
- lockstep bump via bump-version.sh (cli 5 files; admin 5 bumped in admin repo)
- Changelog: v1.2.2 notes for the P0 build/start fix batch (#168)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant