69 lines
3.7 KiB
Markdown
69 lines
3.7 KiB
Markdown
---
|
|
name: prod-db
|
|
description: >-
|
|
Look up data in Cleo production read replicas (Postgres, IAM auth, read-only).
|
|
Use when the user asks to look up, find, or check something in prod / the prod
|
|
DB, e.g. a user id, family id, guide id, or other record IDs for a given
|
|
user. Returns IDs and metadata only, never PII/PHI.
|
|
user-invocable: true
|
|
argument-hint: '[question about prod data]'
|
|
---
|
|
# prod-db
|
|
|
|
Query prod read replicas through one script. Never call `psql` or `aws rds` directly.
|
|
|
|
```sh
|
|
~/.config/claude/skills/prod-db/prod-query.sh <alias> "<select sql>"
|
|
~/.config/claude/skills/prod-db/prod-query.sh <alias> --tables
|
|
~/.config/claude/skills/prod-db/prod-query.sh <alias> --columns <table>
|
|
```
|
|
|
|
The script connects to the `cluster-ro` endpoints as `reader`, forces read-only sessions with a 30s statement timeout, and caps output at 200 rows. If it reports no SSO session, ask the user to run `! aws sso login --profile prod-mono-reader`.
|
|
|
|
## PII/PHI rules (org policy: never put PII/PHI into Claude)
|
|
|
|
- SELECT only IDs, foreign keys, UUIDs, timestamps, statuses, flags and counts.
|
|
- Never select names, emails, phones, DOB, addresses, notes, message bodies, health data, or Kratos `traits`. Never `SELECT *`.
|
|
- A value the user gives you (an email) may appear only in a `WHERE` clause. Do not repeat it in your output; refer to "the user".
|
|
- The script blocks `*`, non-SELECT statements, and result columns whose names look sensitive (it prints only the offending column names). Aliasing a sensitive column to dodge this is forbidden. If the user needs a PII field, tell them to look it up in Postico.
|
|
- Report results as IDs only.
|
|
|
|
## Workflow
|
|
|
|
1. Pick the alias. Run `--tables` / `--columns <table>` (schema only) before writing SQL for an unfamiliar table.
|
|
2. Write a narrow SELECT with explicit columns and a `LIMIT`.
|
|
3. Summarize the IDs. Don't paste raw output beyond what's needed.
|
|
|
|
## Aliases
|
|
|
|
backend (backenddb), guides, kratos, userflow (userpreferencesdb), scheduling (schedulingdb), messaging (messagingdb), eligibility (eligibilitydb), entitlements (entitlementsdb), benefits (benefitsdb), assessments (assessmentsdb), engagement (engagementdb), tagging (taggingdb), supportplan (supportplandb), integrations, content (thegoodcontentdb), retool.
|
|
|
|
## Schema notes
|
|
|
|
**backend** (Django app `lucy_web`, `public` schema):
|
|
- `auth_user(id, email)` is the user.
|
|
- `lucy_web_family(id, employee_user_id, partner_user_id)` links a user to a family, as employee or partner.
|
|
- `lucy_web_childfamilypackage(id, family_id, child_id, guide_id, guide_assigned_on)` links a family to its guide. The current guide is the row with the highest `id` for the family (see `Family.lucy_guide` in `services/cleo-backend/lucy_web/models/family.py`).
|
|
- `lucy_web_lucyguide(id, uuid, user_id, is_active)` is the guide. `user_id` is the guide's own `auth_user` row. Do not select the guide's name or email.
|
|
- Caregiver users are linked through the caregiver childfamilypackage models, which this query does not cover.
|
|
|
|
**guides**: tables store a numeric `guide_id` equal to `lucy_web_lucyguide.id`. It does not own the user-to-guide assignment.
|
|
|
|
**kratos**: `identities(id uuid, traits jsonb)`. The Kratos id is not known to equal backend `auth_user.id`. Bridge on email, inside `WHERE` only. Unverified for this deployment.
|
|
|
|
## Example: user id and guide id for an email
|
|
|
|
```sql
|
|
select u.id as user_id, f.id as family_id,
|
|
g.id as guide_id, g.uuid as guide_uuid, cfp.guide_assigned_on
|
|
from auth_user u
|
|
join lucy_web_family f on f.employee_user_id = u.id or f.partner_user_id = u.id
|
|
join lucy_web_childfamilypackage cfp on cfp.family_id = f.id
|
|
join lucy_web_lucyguide g on g.id = cfp.guide_id
|
|
where lower(u.email) = lower('<email>')
|
|
order by cfp.id desc
|
|
limit 5
|
|
```
|
|
|
|
Run it with alias `backend`.
|