Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions .sandcastle/.env.schema
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,14 @@ INFISICAL_CLIENT_ID=
# @type=infisicalClientSecret @sensitive
INFISICAL_CLIENT_SECRET=

# Add real secrets here as they're introduced, e.g.:
# ANTHROPIC_API_KEY=infisical()
# Claude Code CLI auth for the sandbox container. Sandcastle's docker
# sandbox runs `claude` inside the container, which needs auth — host
# `~/.claude` credentials don't reach the sandbox. We forward this into
# SANDBOX_ENV in main.ts so the in-container CLI can authenticate without
# an interactive `/login`.
#
# Dev-only: Sandcastle is a developer tool — staging/prod environments
# don't run it, so this token is only populated in the `dev` Infisical
# environment. @required=false avoids failing varlock loads in other envs.
# @required=false
CLAUDE_CODE_OAUTH_TOKEN=infisical()
27 changes: 19 additions & 8 deletions .sandcastle/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,25 +46,36 @@ const COPY_TO_WORKTREE: readonly string[] = [];
// fails loudly if a package's main entry is missing.
const INSTALL_AND_VERIFY = "bun install && bun run typecheck";

// Forward the Infisical machine-identity credentials into the sandbox so
// varlock-resolved env (`infisical()` items) works inside the container.
// The credentials live in the host shell env, sourced from the macOS keychain
// via ~/.zshenv. We fail fast if they are missing — the AFK agent cannot
// resolve real env values otherwise, and silent fallback to placeholder
// builds masks misconfiguration.
// Forward credentials into the sandbox container:
// - INFISICAL_CLIENT_ID / _SECRET: machine-identity creds so varlock-resolved
// env (`infisical()` items) works inside the container. Sourced from the
// macOS keychain via ~/.zshenv on the host.
// - CLAUDE_CODE_OAUTH_TOKEN: auth for the in-container `claude` CLI. Without
// this the implementer/reviewer agents fail with `Not logged in · Please
// run /login` because host `~/.claude` credentials don't reach the sandbox.
// Resolved by varlock from Infisical's `dev` environment (this token is
// intentionally absent from staging/prod — sandcastle is dev-only).
//
// The orchestrator is launched via `varlock run --path .sandcastle/` (see the
// `sandcastle` script in the root package.json), so process.env already has
// these values resolved before main.ts runs. We fail fast if they're missing —
// the AFK agent cannot do useful work otherwise, and silent fallback masks
// misconfiguration.
const requireEnv = (key: string): string => {
const value = process.env[key];
if (!value) {
throw new Error(
`${key} is not set on the host. Sandcastle requires Infisical credentials to inject ` +
`into the sandbox so varlock can resolve env values. See CLAUDE.md for keychain setup.`,
`${key} is not set. Sandcastle is launched via \`varlock run\` which should ` +
`resolve this from Infisical (dev env). See .sandcastle/CODING_STANDARDS.md ` +
`for keychain setup.`,
);
}
return value;
};
const SANDBOX_ENV: Record<string, string> = {
INFISICAL_CLIENT_ID: requireEnv("INFISICAL_CLIENT_ID"),
INFISICAL_CLIENT_SECRET: requireEnv("INFISICAL_CLIENT_SECRET"),
CLAUDE_CODE_OAUTH_TOKEN: requireEnv("CLAUDE_CODE_OAUTH_TOKEN"),
};

// ---------- Agent specs ----------
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"env:scan": "varlock scan",
"ci": "TURBO_NO_UPDATE_NOTIFIER=1 turbo typecheck test --output-logs=errors-only && biome check . && bun run check:no-suppressions && bun run env:scan",
"prepare": "husky",
"sandcastle": "bun .sandcastle/main.ts",
"sandcastle": "varlock run --path .sandcastle/ -- bun .sandcastle/main.ts",
"sandcastle:analyze": "bun .sandcastle/analyze.ts",
"sandcastle:build": "bunx sandcastle docker build-image",
"cleanup": "bun scripts/cleanup-branches.ts"
Expand Down
Loading