Skip to content

config: replace dotenv with varlock for env validation#8

Merged
benvinegar merged 1 commit into
mainfrom
benvinegar/varlock-env-schema
Feb 17, 2026
Merged

config: replace dotenv with varlock for env validation#8
benvinegar merged 1 commit into
mainfrom
benvinegar/varlock-env-schema

Conversation

@benvinegar
Copy link
Copy Markdown
Member

Replaces dotenv with Varlock for environment variable management. Adds a committed .env.schema that defines types, required/optional status, and sensitivity for every env var.

What changed

  • .env.schema — new schema file with @required, @sensitive, @type decorators for all 20 env vars. Deployed to ~/.config/.env.schema alongside secrets.
  • start.sh — runs varlock load --path ~/.config/ to validate env before launching. Falls back to plain source if varlock isn't installed.
  • startup-cleanup.sh — bridge tmux session uses varlock run --path ~/.config/ to inject validated env vars. Falls back to source if varlock isn't installed.
  • slack-bridge/bridge.mjs — removed import "dotenv/config". Env vars are now in process.env before Node starts (via varlock run or shell source).
  • slack-bridge/package.json — removed dotenv dependency.
  • bin/deploy.sh — deploys .env.schema to ~/.config/.env.schema (644 perms).
  • CONFIGURATION.md — documents schema validation.

Why

  • Catch misconfigurations at boot — missing required vars, wrong prefixes (xoxb-, ghp_, etc.) fail fast with clear errors instead of crashing deep in a code path
  • Sensitive marking — varlock knows exactly which values are secrets vs config, complementing the existing redact-logs.sh regex approach
  • Schema as documentation — the .env.schema is a single source of truth that stays in sync (unlike .env.example files)
  • Graceful fallback — everything still works without varlock installed (plain source path is preserved)

Tests

All 172 JS tests pass. No behavior changes for existing code paths.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Feb 16, 2026

Greptile Summary

Replaced dotenv with Varlock for environment variable validation at startup, adding fail-fast validation for misconfigurations and type checking with prefix validation (e.g., xoxb-, ghp_).

Key changes:

  • Added .env.schema with @required, @sensitive, and @type decorators for all 20 environment variables
  • Modified start.sh to run varlock load before sourcing .env (with graceful fallback if varlock not installed)
  • Updated startup-cleanup.sh to use varlock run when launching the bridge (also includes fallback)
  • Fixed bug in startup-cleanup.sh where bridge was incorrectly started from ~/hornet/slack-bridge (source repo) instead of ~/runtime/slack-bridge (deployed path)
  • Removed dotenv dependency from slack-bridge/package.json since env vars are now injected before Node starts
  • Updated bin/deploy.sh to deploy .env.schema to ~/.config/.env.schema with 644 permissions
  • Updated CONFIGURATION.md to document the new validation approach

All changes maintain backward compatibility with graceful fallback to plain source if varlock is not installed.

Confidence Score: 5/5

  • This PR is safe to merge with no risk
  • Clean implementation that adds validation without breaking changes. The graceful fallback to plain source ensures backward compatibility. All 172 tests pass. Bonus: fixes an existing bug where the bridge was incorrectly started from the source repo path instead of the deployed runtime path.
  • No files require special attention

Important Files Changed

Filename Overview
.env.schema Added comprehensive schema with decorators for all 20 env vars, defining types, required status, and sensitivity
start.sh Added varlock validation before env loading with graceful fallback to plain source if varlock not installed
pi/skills/control-agent/startup-cleanup.sh Fixed bug (~/hornet → ~/runtime path) and added varlock support with fallback for bridge startup
slack-bridge/bridge.mjs Removed dotenv import since env vars are now injected before Node starts via varlock or shell source
bin/deploy.sh Added deployment of .env.schema to ~/.config/.env.schema with 644 permissions

Flowchart

flowchart TD
    A[Admin runs deploy.sh] --> B[Deploy .env.schema to ~/.config/]
    B --> C[User runs start.sh]
    C --> D{varlock installed?}
    D -->|Yes| E[varlock load --path ~/.config/]
    D -->|No| F[source ~/.config/.env]
    E --> G{Validation passed?}
    G -->|Yes| H[Export vars to process.env]
    G -->|No| I[Exit with error message]
    F --> H
    H --> J[Run harden-permissions.sh]
    J --> K[Start control-agent]
    K --> L[startup-cleanup.sh runs]
    L --> M{varlock installed?}
    M -->|Yes| N[varlock run -- node bridge.mjs]
    M -->|No| O[source .env && node bridge.mjs]
    N --> P[bridge.mjs starts with validated env]
    O --> P
    P --> Q[Bridge validates required vars]
    Q --> R[Bridge operational]
Loading

Last reviewed commit: d714e4a

@benvinegar benvinegar force-pushed the benvinegar/varlock-env-schema branch 2 times, most recently from 4698f85 to 651e743 Compare February 16, 2026 22:19
@benvinegar benvinegar changed the title security: add varlock env schema for startup validation config: replace dotenv with varlock for env validation Feb 16, 2026
@benvinegar benvinegar force-pushed the benvinegar/varlock-env-schema branch from 651e743 to 8e2afcd Compare February 16, 2026 22:21
Comment thread pi/skills/control-agent/startup-cleanup.sh
@benvinegar benvinegar force-pushed the benvinegar/varlock-env-schema branch from 8e2afcd to 5a192b4 Compare February 17, 2026 02:05
- Add .env.schema with types, @required, @sensitive decorators for all env vars
- Remove dotenv from slack-bridge, env vars now injected via varlock run
- start.sh validates with `varlock load` before launching
- startup-cleanup.sh uses `varlock run` for bridge tmux session
- deploy.sh deploys .env.schema to ~/.config/.env.schema
- setup.sh installs varlock binary
- Update CONFIGURATION.md with schema validation docs

Replaces blind dotenv loading with schema-validated startup. Catches
wrong token prefixes, missing required vars, and invalid emails before
any connections are attempted.
@benvinegar benvinegar force-pushed the benvinegar/varlock-env-schema branch from 5a192b4 to c53ee4c Compare February 17, 2026 02:06
Comment thread start.sh
Comment on lines +20 to +23
varlock load --path ~/.config/ || {
echo "❌ Environment validation failed — check ~/.config/.env against .env.schema"
exit 1
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The script introduces a hard dependency on varlock. If varlock is not installed, the agent and Slack bridge will fail to start, contrary to the promised graceful fallback.
Severity: HIGH

Suggested Fix

Before calling varlock, check if the command exists using command -v varlock >/dev/null. If it exists, use varlock. Otherwise, fall back to the plain source ~/.config/.env command. This will implement the graceful fallback described in the pull request description.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: start.sh#L20-L23

Potential issue: The scripts `start.sh` and `startup-cleanup.sh` directly call `varlock`
without first checking if it is installed or available in the `PATH`. If the `varlock`
command is not found, `start.sh` will exit with an error instead of falling back to
`source ~/.config/.env`. Similarly, the `tmux` session for the Slack bridge in
`startup-cleanup.sh` will fail to start. This contradicts the PR's goal of providing a
graceful fallback and will cause startup failures if the `varlock` installation fails
for any reason.

@benvinegar benvinegar merged commit 26fff12 into main Feb 17, 2026
6 checks passed
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