# Secrets & protected files

hlix does not solve local-to-cloud by dropping secret files. It moves them through a separate protected-data path so the cloud environment can behave like the local project without committing credentials into its Git history.

## What the scanner collects

Recognized protected files include:

- `.env` and environment-specific dotenv files, except examples/templates
- `.envrc`, with literal assignments collected without executing shell code
- credential and service-account JSON
- `.npmrc` and `.pypirc`
- private-key and certificate-key formats such as `.pem`, `.key`, `.p12`, and `.pfx`
- `terraform.tfvars` and `terraform.tfvars.json`
- regular text files containing a high-confidence private-key or provider-token pattern
- quarantined agent, skill, and MCP configuration

The dry-run report lists paths and key names, never values:

```bash
hlix import . --dry-run --json
```

## Dotenv selection

When no override is provided, hlix composes development dotenv files in this order:

1. `.env`
2. `.env.development`
3. `.env.local`
4. `.env.development.local`

Later assignments win. Use an explicit file when the inferred development environment is not the one intended for cloud:

```bash
hlix import . --dry-run --env-file .env.cloud-development
hlix import . --env-file .env.cloud-development
```
**Collection is intentional, not silent:** Import preserves every recognized protected file, while the selected dotenv file(s) determine the key/value set exposed as project secrets. Review `activeEnvFiles`, `secretKeys`, and `envCollisions` in the dry-run output before upload.

### Direnv and dynamic secret managers

Literal `.envrc` assignments join the selected development secret set. Dynamic shell expressions are not executed during scanning. If your active shell already contains the resolved project key—for example after direnv called 1Password, Infisical, or Doppler—Hlix collects that resolved value. Otherwise import blocks so you can activate the environment before retrying.

## Data path

The seven steps cross three trust zones: your machine records only metadata and sends protected files separately, the backend verifies every hash and encrypts at rest, and the Coding Workspace revalidates the bytes, writes them `0600`, and strips them from every commit.

1. The local scanner reads protected bytes into memory and records only path, kind, size, hash, and key names in the manifest.
2. Protected files are omitted from the Git snapshot and sent separately over the authenticated TLS API request.
3. The backend checks that every supplied path, kind, size, and SHA-256 exactly matches the manifest.
4. Values and file contents are encrypted at rest with AES-GCM under the deployment's secrets-encryption key.
5. For an authorized task, the backend decrypts the protected project files and sends them in the task payload through the sandbox filesystem—not command arguments.
6. The sandbox validates the bytes again, refuses traversal and symlink targets, writes files with mode `0600`, and pins their exact paths in Git exclude rules.
7. Commit staging explicitly removes every protected path as a final guard.

The same integrity checks apply in reverse during `hlix pull`.

## Who can access values

Encryption at rest is not end-to-end encryption. The hlix backend must be able to decrypt values for authorized project work and authenticated pull. A project task, its selected coding agent, and repository setup commands can read materialized values inside that project's Coding Workspace.

Use least-privileged, environment-specific credentials. Do not import a personal all-access token when a project-scoped development token will work.

## Failure behavior

Secret resolution is fail-closed. If protected data cannot be decrypted or a required secret cannot be resolved, task dispatch stops instead of starting with an empty or partial environment.

Known secret values and protected-file contents are included in execution-log redaction. Redaction covers exact values, lines, and dotenv-style assignment values. It is defense in depth—not a reason to print credentials. Encoded, transformed, split, or novel values may not match exact-value redaction.

## Git history is separate

Excluding a current `.env` file does not erase an older committed value. Import scans up to 10,000 commits for sensitive paths and high-confidence patterns and blocks by default when it finds them.

If a credential entered Git history:

1. Rotate or revoke it first.
2. Decide whether history must be rewritten.
3. Verify the rewritten repository independently.
4. Re-run `hlix import . --dry-run`.

`--history preserve` retains the history despite findings. It is an informed retention decision, not remediation.

## Keep secrets synchronized

Protected files participate in the project manifest. Edit them locally, then create a new revision:

```bash
hlix push
```

Pulling a cloud revision restores protected bytes with owner-only permissions:

```bash
hlix pull
```

If both local and cloud protected state changed, `hlix sync` refuses to guess. Review the conflict and select a direction explicitly.

## If a secret does not reach the workspace

- **A task fails immediately with an empty credential.** The key name was imported but its value was not. Add the value at its declared source and push a new revision; MCP and environment configuration carry key *names* only.
- **`hlix import` blocks on a missing key.** A key the project *declares* is fatal; one it only *references* in source is a warning. Provide the declared value, or remove the declaration.
- **The wrong dotenv profile was activated.** Re-import or push with `--env-file <path>`; every other profile was preserved encrypted, so nothing was lost.
- **A `.envrc` key is empty.** Dynamic assignments are never executed. Let direnv resolve it into your shell, then scan again.
- **`hlix sync` refuses after protected state changed on both sides.** It does not guess. Review the conflict and choose a direction with `push` or `pull` explicitly.
- **A value you rotated at the provider still works in a task.** The project holds its own encrypted copy. Rotating at the provider is not the same as updating the project; push a new revision.
- **A secret appears in a dry-run report.** It does not — only key names, hashes, sizes, and paths do. If you believe you are seeing a value, treat it as a defect and report it rather than sharing the report.

## Operational checklist

- Use development credentials with narrow project scope.
- Rotate anything that was exposed in source control, logs, chat, or issue trackers.
- Keep the deployment encryption key configured, access-controlled, and backed up according to your recovery policy.
- Treat access to project manage/sync APIs as access to protected project material.
- Review MCP environment key names before activation.
- Delete stale credentials at the provider, not only from a dotenv file.

## Next steps

[Import trust model](/security/trust-model/)
  [Environment discovery](/cli/environment-discovery/)
  [Import skills, agents & MCP](/cli/resources/)
  [hlix push, pull & sync](/reference/cli/sync/)