# instinct: tools/*.py の本番postgres PWハードコードは .env の DATABASE_URL(ソケットpeer認証)に置き換える。env_configの副作用importは development環境で失敗するので使わない
vvv-bots の `tools/*.py` が `postgresql://postgres:<実PW>@127.0.0.1:5432/...` をハードコードしている場合、`.env` の `DATABASE_URL` に置き換える。本番の `.env` は **Unixソケットpeer認証**(`postgresql://...@/vvv_prod?host=/var/run/postgresql`)で**パスワード不要**。
## 正しいパターン(同フォルダに既存のお手本あり)
`tools/channel_scoring.py` / `semantic_alert.py` が手本。ただし `.env` 読込方法に注意:
```python
# ✅ 確実: 自前の _read_env_key で .env から直読み(cron実行でも動く)
_ENV_FILE_CANDIDATES = [Path(".../vvv-bots/.env"), Path(".../vvv/.env.master"), BASE_DIR/".env"]
def _read_env_key(key): ... # .env を行走査して値を返す
DB_URL = _read_env_key("DATABASE_URL")
```
## ⚠️ env_config の副作用importは使うな(罠)
`import env_config`(load_dotenvの副作用狙い)は **worktree/開発環境で `DATABASE_URL_DEV` を要求して `ValueError` で落ちる**(env_config.py:67 setup_environment が environment=development を検出)。`db_utils.get_db_url()` も `os.getenv('DATABASE_URL')` 前提で、env_config が先に走らないと空。→ 自前 `_read_env_key` で `.env` を直読みするのが最も確実。
## 副次バグも疑え
`embed_videos.py` はハードコードURLが `.../postgres`(存在しないDB)を指し、**videosテーブルが0件で実質機能していなかった**。正しくは `vvv_prod`。ハードコード修正時に「そもそも正しいDBを見ているか」も確認する(`SELECT count(*) FROM information_schema.tables WHERE table_name='videos'` を各DBで)。
## 検証
- 修正後は実機で `--dry-run` 等を本番venvで走らせ「DB接続成功・件数取得」を確認(peer認証で繋がるか)
- `grep -c '<旧PWの一部>' file` で 0 を確認・ruff All checks passed
- cron実行されるファイル(`crontab -l | grep`)は本番フォルダ同期(`git pull`)まで必須
## 関連
- [[instinct-postgres-pw-rotation-socket-safe]] — アプリはpeer接続でpostgres実PW未使用
- [[instinct-env-permission-drift-664]] — security時は全.env一括点検
- vvv-bots#248(shadowセキュリティ監査・新規finding)
---
(migrated from local memory/instinct_tools_hardcoded_db_use_socket_peer.md)
instinct: tools/*.py の本番postgres PWハードコードは .env の DATABASE_URL(ソケットpeer認証)に置き換える。env_configの副作用importは development環境で失敗するので使わない