---
name: env-secret
description: >
  Read or write application secrets in AWS Secrets Manager.
  Use when the user says /env-secret, 'quelle est la valeur de', 'env var en prod',
  'secret manager', 'variable d environnement', 'check env var', 'set secret',
  'ajoute un secret', 'met a jour le secret', 'update secret', or needs to find
  or modify config variables for a given environment.
argument-hint: "<variable name or keyword> [environment: dev, test, review, prod (default: dev)] [--no-local] [--set key=$ENV_VAR key2=value ...]"
allowed-tools:
  - Read
  - Bash
hooks:
  - type: PreToolUse
    matcher: Bash
    hook: |
      BLOCKED_PATTERNS='echo.*SECRET|echo.*MGMT|cat.*/tmp/aws_secret|print.*secret_value|printf.*SECRET'
      if echo "$TOOL_INPUT" | grep -qEi "$BLOCKED_PATTERNS"; then
        echo "BLOCKED: potential secret leak detected. Never echo, cat, or print secret values."
        exit 2
      fi
---

Read or write application secrets stored in AWS Secrets Manager.

## Required tools

- `aws`

Run `pysae-ai-tools tools require <tools>` before starting; if it exits non-zero, abort and report the install command from stderr to the user.

## Mode detection

Parse `$ARGUMENTS` to determine the mode:

- If `--set` is present → **write mode** (see [Write mode](#write-mode))
- Otherwise → **read mode** (see [Read mode](#read-mode))

## Environment mapping

Both modes use the same mapping:

| Environment     | Secret name             |
|-----------------|-------------------------|
| `dev` (default) | `pysae/dev/secrets`     |
| `test`          | `pysae/testing/secrets` |
| `review`        | `pysae/review/secrets`  |
| `prod`          | `pysae/prod/secrets`    |

### Local overrides (read mode only)

| Environment | Local override secret      |
|-------------|----------------------------|
| `dev`       | `pysae/local-dev/secrets`  |
| `prod`      | `pysae/local-prod/secrets` |
| `test`      | *(none)*                   |
| `review`    | *(none)*                   |

### Secrets personnels IAM

Chaque utilisateur AWS peut stocker des secrets personnels sous le préfixe `/iam/<username>/*`, où `<username>` est le nom d'utilisateur IAM. Ces secrets sont propres à l'utilisateur et ne sont pas partagés avec les environnements applicatifs.

Pour déterminer le username courant :
```bash
IAM_USER=$(aws sts get-caller-identity --query 'Arn' --output text | grep -oP '(?<=/)[^/]+$')
```

Exemples d'utilisation :
- `/iam/remi/api-tokens` — tokens d'API personnels
- `/iam/remi/dev-overrides` — overrides de dev locaux

Les mêmes règles de sécurité s'appliquent : valeurs masquées par défaut, jamais de leak dans les logs.

---

## Read mode

Default mode when `--set` is absent.

1. **Parse arguments** — extract keyword and target environment from `$ARGUMENTS`. Default to `dev`.

2. **Fetch and merge secrets** — unless `--no-local` is specified:
   ```bash
   MAIN_JSON=$(aws secretsmanager get-secret-value \
     --secret-id "<main-secret>" \
     --query 'SecretString' \
     --output text)

   LOCAL_JSON=$(aws secretsmanager get-secret-value \
     --secret-id "pysae/local-<env>/secrets" \
     --query 'SecretString' \
     --output text 2>/dev/null || echo '{}')

   SECRET_JSON=$(echo "$MAIN_JSON $LOCAL_JSON" | jq -s '.[0] * .[1]')
   ```

3. **Search for the variable** — check the [secret keys detail](../references/pysae-projects.md#secret-keys-detail) for known mappings between secret keys, env vars, and API flavors (e.g. `MONGO_URI` → `api-mongo-uri`). Then fuzzy match on keys containing the keyword.

4. **Display the result** — show matching key(s) but **NEVER the values**:
   > **Environment** : `dev` (avec overrides locaux)
   > **Key** : `api-mongo-uri`
   > **Value** : `********`

   Only reveal the actual value if the user **explicitly asks** to see it.

5. **Usage in scripts** — inject as environment variable without displaying:
   ```bash
   export MY_VAR=$(echo "$SECRET_JSON" | jq -r '."<KEY>"')
   ```

---

## Write mode

Activated when `--set` is present in `$ARGUMENTS`.

### Argument format

```
/env-secret --set key=value key2=$ENV_VAR [environment]
```

- `key=value` — literal value
- `key=$ENV_VAR` — resolved from environment variable at runtime (never displayed)

### Process

1. **Parse** key=value pairs and target environment.

2. **Confirm before writing** — display keys only, values masked:
   > **Environment** : `dev`
   > **Secret** : `pysae/dev/secrets`
   > **Keys to set** :
   > - `api-auth0-mgmt-client-id` = `yaJuNw...` (literal, 32 chars)
   > - `api-auth0-mgmt-client-secret` = `$AUTH0_MGMT_SECRET_DEV` (from env var)
   >
   > Confirmer ?

   For prod, **ALWAYS require explicit confirmation** with a warning.

3. **Execute the bundled script** — pass the secret ID and key=value pairs as arguments:
   ```bash
   pysae-ai-tools env secret set \
     "pysae/dev/secrets" \
     "api-auth0-mgmt-client-id=yaJuNwMi..." \
     "api-auth0-mgmt-client-secret=$AUTH0_MGMT_SECRET_DEV"
   ```
   The script handles fetch → merge → write → cleanup. Prints only `OK` or `FAILED: <reason>`.

4. **Verify** — confirm keys exist (values masked):
   ```bash
   aws secretsmanager get-secret-value \
     --secret-id "<secret-id>" \
     --query 'SecretString' \
     --output text \
     | python3 -c "import json,sys; s=json.load(sys.stdin); [print(f'  {k}: present') for k in sorted(s) if '<keyword>' in k]"
   ```

5. **Report** :
   > **Updated** : `pysae/dev/secrets`
   > **Keys set** : `api-auth0-mgmt-client-id`, `api-auth0-mgmt-client-secret`
   > **Status** : OK

---

## Gotchas

- **`test` maps to `pysae/testing/secrets`** — not `pysae/test/secrets`. This is the #1 source of "key not found" confusion.
- **Shell escaping kills one-liners** — never try to inline Python with secret values in a bash one-liner. The bundled `pysae_ai_tools.env.secret` exists specifically to avoid this. Use it.
- **ESO sync takes up to 1 hour** — after updating AWS Secrets Manager, the K8s Secret won't reflect the change immediately. Force sync with:
  ```bash
  kubectl annotate externalsecret --all -n pysae force-sync=$(date +%s) --overwrite
  ```
- **Security hooks block `/dev/` in paths** — the path `pysae/dev/secrets` contains `/dev/` which some security hooks interpret as the system device path. If a command is blocked, use the bundled Python script instead of raw aws CLI.
- **Prod and dev use different Auth0 tenants** — the same secret keys (e.g. `api-auth0-mgmt-client-id`) have different values per environment. Never copy prod credentials to dev or vice versa.
- **Env var references with `$` must exist** — if you pass `key=$MY_VAR` and `MY_VAR` is not set in the current shell, the script fails. Set it with `export MY_VAR=...` first, or use `! export MY_VAR=...` in Claude Code.

## Rules

- **Values masked by default** — display `********` instead of the actual value, for ALL environments and modes. Only reveal on explicit user request (read mode only, never in write mode).
- **Never leak values** — never display secret values in tool call output, error messages, logs, or commits.
- **Never pass secrets as CLI arguments** — use env vars, files, or the bundled script.
- **Prod requires confirmation** — always ask and warn before writing to prod.

$ARGUMENTS
