Skip to content

Reserve the _SAGE_* env namespace as cloud-managed and read-only#261

Open
cvince wants to merge 1 commit into
mainfrom
cvince/sage-managed-namespace
Open

Reserve the _SAGE_* env namespace as cloud-managed and read-only#261
cvince wants to merge 1 commit into
mainfrom
cvince/sage-managed-namespace

Conversation

@cvince

@cvince cvince commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

What

Introduces a reserved environment-variable namespace: any variable whose name begins with _SAGE_ is managed by a Capy cloud runtime, and the cloud copy is authoritative. The CLI now treats the entire namespace as read-only on the local machine.

The rule lives in one place — isReservedNamespace() in src/core/reservedNamespace.ts — and every surface enforces it the same way:

Surface Behavior
capy run Reserved vars are stripped from the spawned child process's environment and from the generated .capy/next-env.js build-time module. They are the runtime's own tooling, not the application's secrets.
capy sync Reserved vars are never reconciled — no push, pull, conflict, or local-delete propagation. The cloud value always wins, so a stale local copy can neither overwrite it nor raise a spurious conflict.
capy edit Reserved vars are never listed, so they can't be edited locally.

Why

These variables are written and owned by a cloud-side runtime. Letting the local CLI push, conflict-resolve, or hand-edit them would let a stale workstation overwrite authoritative cloud state. Excluding them from capy run injection also keeps that tooling out of application processes that have no business seeing it.

Tests

  • Unit (tests/sync/syncEngine.test.ts): no reserved var ever lands in any reconciliation bucket (push/pull/conflict/unchanged/delete), and a previously-synced reserved var is not treated as a local deletion.
  • End-to-end (tests/commands/runCommand.test.ts): the capy run exclusion in both local-.env and deployed (SECRETS_BLOB) modes — app vars pass through, reserved vars do not, and next-env.js omits them.

Full CLI suite green (bash tests/run-tests.sh).

Variables prefixed `_SAGE_` are managed by a Capy cloud runtime, and the
cloud copy is authoritative. The CLI now treats the whole namespace as
read-only locally, enforced through one shared predicate
(`isReservedNamespace`) so every surface behaves the same way:

- `capy run` never injects these into the spawned child process, nor into
  the Next.js build-time env module — they are the runtime's own tooling,
  not the application's secrets.
- sync never reconciles them: no push, pull, conflict, or local-delete
  propagation. The cloud value always wins, so a stale local copy can
  never overwrite it or surface a spurious conflict.
- `capy edit` never lists them, so they cannot be edited locally.

Tests: unit coverage for the sync exclusion (no reserved var ever lands in
any reconciliation bucket, and a previously-synced reserved var is not
treated as a local deletion), plus end-to-end coverage for the `capy run`
exclusion in both local and deployed modes.
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