{ "_provenance": { "note": "EDITABLE ruleset for 'Actions worth reviewing' (the Session/Project Report safety lens). Each rule flags a NAMED, high-impact operation in a Bash command and tags it. Add a tool by adding a rule — no code change. The engine applies structural guards on top of every rule: it skips read/search contexts (grep/cat/sed/...), skips --help/--version/-h invocations, and for SQL-privilege/data rules it REQUIRES a real database client on the command's first line (so a grep for 'CREATE ROLE' or a python heredoc carrying it as a string never counts). Suggest-only, cites the turn (non-negotiables #1/#7).", "updated": "2026-06-06", "tags": { "LIVE": "Modified a live/deployed service (deploy, redeploy, restart, scale, exec-in, set hosted vars/secrets, down/remove). In Her, ANY change to a running service counts — dev, staging, or prod.", "NETWORK": "Opened a tunnel/proxy or exposed a service to other networks.", "SECURITY": "Changed a privilege, credential, IAM policy, or permission.", "DATA": "Destructive or schema-level data change (drop/truncate/delete, migrations, object/bucket deletes).", "CONFIG": "Wrote a local config/secret file (e.g. an .env)." } }, "rules": [ {"id": "railway-deploy", "tag": "LIVE", "title": "Deployed / changed a Railway service", "detail": "An app was deployed, redeployed, restarted, scaled, or removed on Railway.", "match": "\\brailway\\s+(up|redeploy|deploy|down|restart|remove|delete|scale|add)\\b"}, {"id": "railway-exec", "tag": "LIVE", "title": "Ran commands inside a live Railway service", "detail": "Commands were executed in a deployed Railway service (railway ssh / run).", "match": "\\brailway\\s+(ssh|run)\\b"}, {"id": "railway-vars", "tag": "LIVE", "title": "Changed Railway service variables", "detail": "Environment variables were set on a Railway service.", "match": "\\brailway\\s+variables?\\s+(--set|set|--kv)\\b"}, {"id": "railway-volume", "tag": "LIVE", "title": "Changed a Railway volume", "detail": "A Railway volume was added, attached, or deleted.", "match": "\\brailway\\s+volume\\s+(add|attach|detach|delete|remove)\\b"}, {"id": "vercel-deploy", "tag": "LIVE", "title": "Deployed to Vercel", "detail": "A deployment was pushed, promoted, or rolled back on Vercel.", "match": "\\bvercel\\s+(deploy|--prod|promote|rollback|redeploy)\\b"}, {"id": "vercel-env", "tag": "LIVE", "title": "Changed Vercel environment", "detail": "Environment variables were added or removed on Vercel.", "match": "\\bvercel\\s+env\\s+(add|rm|pull\\s+--environment=production)\\b"}, {"id": "netlify-deploy", "tag": "LIVE", "title": "Deployed to Netlify", "detail": "A site or environment change was pushed to Netlify.", "match": "\\bnetlify\\s+(deploy|env:set|env:import|env:unset)\\b"}, {"id": "fly-deploy", "tag": "LIVE", "title": "Deployed / changed a Fly.io app", "detail": "An app was deployed, scaled, restarted, or had secrets set on Fly.io.", "match": "\\bfly(ctl)?\\s+(deploy|scale|restart|ssh\\s+console|secrets\\s+(set|import|unset)|machine\\s+(start|stop|restart|destroy)|apps\\s+(restart|destroy|create))\\b"}, {"id": "wrangler-deploy", "tag": "LIVE", "title": "Deployed to Cloudflare", "detail": "A Worker/Pages deploy, secret, or KV/R2/D1 change went to Cloudflare's edge.", "match": "\\bwrangler\\s+(deploy|publish|rollback|secret\\s+put|pages\\s+deploy|kv:[a-z]+\\s+(put|delete)|kv\\s+key\\s+(put|delete)|d1\\s+execute)\\b"}, {"id": "cloudflare-r2-del", "tag": "DATA", "title": "Deleted Cloudflare R2 objects", "detail": "Objects were deleted from R2 storage.", "match": "\\bwrangler\\s+r2\\s+object\\s+delete\\b"}, {"id": "aws-deploy", "tag": "LIVE", "title": "Changed AWS infrastructure / service", "detail": "An AWS service was deployed, updated, or had instances changed.", "match": "\\baws\\s+(ecs\\s+(update-service|create-service)|lambda\\s+(update-function-code|update-function-configuration|create-function)|cloudformation\\s+(deploy|create-stack|update-stack|delete-stack)|elasticbeanstalk\\s+|apprunner\\s+(create|update|start|pause)|ec2\\s+(run-instances|terminate-instances|stop-instances|start-instances|reboot-instances)|rds\\s+(modify-db-instance|reboot-db-instance|delete-db-instance|create-db-instance)|amplify\\s+(start-deployment|create-deployment)|apigateway\\s+create-deployment|deploy\\s+create-deployment)\\b"}, {"id": "aws-s3-upload", "tag": "LIVE", "title": "Uploaded to an S3 bucket", "detail": "Files were copied or synced to S3.", "match": "\\baws\\s+s3\\s+(cp|sync|mv)\\b"}, {"id": "aws-s3-del", "tag": "DATA", "title": "Deleted from S3", "detail": "Objects or a bucket were removed from S3.", "match": "\\baws\\s+s3\\s+(rm|rb)\\b|\\baws\\s+s3api\\s+delete-(object|bucket)\\b"}, {"id": "aws-secrets", "tag": "LIVE", "title": "Changed AWS secrets / parameters", "detail": "A Secrets Manager secret or SSM parameter was written.", "match": "\\baws\\s+(ssm\\s+put-parameter|secretsmanager\\s+(create-secret|put-secret-value|update-secret))\\b"}, {"id": "aws-iam", "tag": "SECURITY", "title": "Changed AWS IAM", "detail": "An IAM user, role, policy, or access key was created or attached.", "match": "\\baws\\s+iam\\s+(create-user|create-role|create-policy|attach-[a-z-]+-policy|put-[a-z-]+-policy|create-access-key|add-user-to-group|create-login-profile)\\b"}, {"id": "gcloud-deploy", "tag": "LIVE", "title": "Deployed / changed Google Cloud", "detail": "A Cloud Run/App Engine/Functions deploy or compute/SQL change ran on GCP.", "match": "\\bgcloud\\s+(run\\s+deploy|app\\s+deploy|functions\\s+deploy|builds\\s+submit|container\\s+clusters\\s+(create|delete|resize|upgrade)|compute\\s+instances\\s+(create|delete|start|stop|reset)|sql\\s+(instances\\s+(create|delete|patch)|users\\s+(create|set-password))|deploy)\\b"}, {"id": "gcloud-secrets", "tag": "LIVE", "title": "Changed Google Cloud secrets", "detail": "A Secret Manager secret was created or a version added.", "match": "\\bgcloud\\s+secrets\\s+(create|versions\\s+add)\\b"}, {"id": "gcloud-iam", "tag": "SECURITY", "title": "Changed Google Cloud IAM", "detail": "An IAM policy binding or service account was changed.", "match": "\\bgcloud\\s+(projects\\s+(add-iam-policy-binding|set-iam-policy|remove-iam-policy-binding)|iam\\s+(service-accounts\\s+(create|keys\\s+create)|roles\\s+create))\\b"}, {"id": "az-deploy", "tag": "LIVE", "title": "Deployed / changed Azure", "detail": "An Azure web app, container app, AKS, or VM was deployed or changed.", "match": "\\baz\\s+(webapp\\s+(up|deploy|restart|create)|containerapp\\s+(up|create|update)|aks\\s+(create|delete|scale|start|stop)|vm\\s+(create|delete|start|stop|restart)|functionapp\\s+(create|deployment)|deployment\\s+(group\\s+)?create)\\b"}, {"id": "az-iam", "tag": "SECURITY", "title": "Changed Azure roles", "detail": "An Azure role assignment or AD object was changed.", "match": "\\baz\\s+(role\\s+assignment\\s+(create|delete)|ad\\s+(user|sp|app)\\s+create)\\b"}, {"id": "kubectl-change", "tag": "LIVE", "title": "Changed a Kubernetes cluster", "detail": "A cluster resource was applied, deleted, patched, scaled, or exec'd into.", "match": "\\bkubectl\\s+(apply|create|delete|replace|patch|rollout|scale|edit|exec|cordon|drain|set\\s+(image|env|resources))\\b"}, {"id": "kubectl-portfwd", "tag": "NETWORK", "title": "Forwarded a cluster port", "detail": "A Kubernetes port was forwarded to localhost.", "match": "\\bkubectl\\s+port-forward\\b"}, {"id": "helm", "tag": "LIVE", "title": "Changed a Helm release", "detail": "A Helm chart was installed, upgraded, rolled back, or uninstalled.", "match": "\\bhelm\\s+(install|upgrade|uninstall|rollback)\\b"}, {"id": "docker-push", "tag": "LIVE", "title": "Pushed a container image", "detail": "A Docker image was pushed to a registry.", "match": "\\bdocker\\s+push\\b"}, {"id": "docker-swarm", "tag": "LIVE", "title": "Changed a Docker service/stack", "detail": "A Docker Swarm service or stack was created, updated, scaled, or removed.", "match": "\\bdocker\\s+(service|stack)\\s+(create|update|deploy|scale|rm)\\b"}, {"id": "docker-compose", "tag": "DEV", "title": "Ran local containers (docker compose)", "detail": "Containerized services were started, stopped, or restarted locally.", "match": "\\bdocker(\\s+compose|-compose)?\\s+(up|down|start|stop|restart|kill|rm)\\b"}, {"id": "docker-exec", "tag": "DEV", "title": "Ran a command inside a container", "detail": "Commands were executed in a running container (docker exec).", "match": "\\bdocker\\s+exec\\b"}, {"id": "docker-run", "tag": "DEV", "title": "Ran a container (docker run)", "detail": "A container was launched with docker run.", "match": "\\bdocker\\s+run\\b"}, {"id": "llama-server", "tag": "DEV", "title": "Started a local LLM server (llama.cpp)", "detail": "A local llama.cpp model server was started.", "match": "\\b(llama-server|llama-cli|llama_cpp\\.server)\\b"}, {"id": "ollama", "tag": "DEV", "title": "Ran a local model (Ollama)", "detail": "A local model was served or run via Ollama.", "match": "\\bollama\\s+(serve|run|create|pull)\\b"}, {"id": "dev-server-js", "tag": "DEV", "title": "Started a local dev server", "detail": "A JS/TS dev server was started locally.", "match": "\\b(vite|nodemon|ts-node-dev)\\b|\\b(next|nuxt|remix|astro|ng)\\s+(dev|serve)\\b|\\b(npm|pnpm|yarn|bun)\\s+(run\\s+)?(dev|start|serve)\\b|\\bwebpack\\s+serve\\b"}, {"id": "dev-server-py", "tag": "DEV", "title": "Started a local Python server", "detail": "A Python web/dev/notebook server was started locally.", "match": "\\b(uvicorn|gunicorn|hypercorn|daphne|streamlit\\s+run|gradio)\\b|\\bflask\\s+run\\b|\\bpython\\d?\\s+-m\\s+(flask|uvicorn|http\\.server)\\b|\\bmanage\\.py\\s+runserver\\b|\\bjupyter\\s+(notebook|lab|server)\\b"}, {"id": "dev-server-node", "tag": "DEV", "title": "Ran a Node server", "detail": "A Node entrypoint (server/app/index/main) was run locally.", "match": "\\bnode\\s+[\\w./-]*(server|app|index|main)[\\w./-]*\\.(js|mjs|cjs|ts)\\b"}, {"id": "dev-server-other", "tag": "DEV", "title": "Started a local dev server", "detail": "A local dev/static server was started.", "match": "\\b(rails\\s+s(erver)?|php\\s+-S|hugo\\s+server|jekyll\\s+serve|http-server|live-server|serve\\s+-)\\b"}, {"id": "terraform-apply", "tag": "LIVE", "title": "Applied infrastructure (Terraform)", "detail": "Real infrastructure was created or changed.", "match": "\\bterraform\\s+apply\\b"}, {"id": "terraform-destroy", "tag": "DATA", "title": "Destroyed infrastructure (Terraform)", "detail": "Infrastructure was destroyed.", "match": "\\bterraform\\s+destroy\\b"}, {"id": "pulumi", "tag": "LIVE", "title": "Changed infrastructure (Pulumi)", "detail": "A Pulumi stack was updated or destroyed.", "match": "\\bpulumi\\s+(up|update|destroy)\\b"}, {"id": "heroku", "tag": "LIVE", "title": "Changed a Heroku app", "detail": "A Heroku release, scale, restart, config, or run happened.", "match": "\\bheroku\\s+(releases:|ps:scale|restart|config:set|config:unset|run|pg:|addons:create|domains:add)\\b"}, {"id": "supabase-deploy", "tag": "LIVE", "title": "Changed Supabase", "detail": "A Supabase db push, function deploy, secret, or link ran.", "match": "\\bsupabase\\s+(db\\s+push|functions\\s+deploy|secrets\\s+set|link)\\b"}, {"id": "supabase-reset", "tag": "DATA", "title": "Reset a Supabase database", "detail": "A Supabase database was reset.", "match": "\\bsupabase\\s+db\\s+reset\\b"}, {"id": "firebase", "tag": "LIVE", "title": "Deployed to Firebase", "detail": "Firebase hosting, functions, or rules were deployed.", "match": "\\bfirebase\\s+(deploy|functions:|hosting:)\\b"}, {"id": "firebase-del", "tag": "DATA", "title": "Deleted Firestore data", "detail": "Firestore documents were deleted.", "match": "\\bfirebase\\s+firestore:delete\\b"}, {"id": "convex", "tag": "LIVE", "title": "Deployed to Convex", "detail": "A Convex deployment ran.", "match": "\\bconvex\\s+(deploy|import|run)\\b"}, {"id": "n8n", "tag": "LIVE", "title": "Changed n8n workflows", "detail": "n8n workflows were imported, updated, or executed.", "match": "\\bn8n\\s+(import:workflow|update:workflow|execute|deploy)\\b"}, {"id": "pm2", "tag": "LIVE", "title": "Changed running processes (PM2)", "detail": "PM2 started, restarted, reloaded, or deployed a process.", "match": "\\bpm2\\s+(start|restart|reload|stop|delete|deploy)\\b"}, {"id": "ansible", "tag": "LIVE", "title": "Ran an Ansible playbook", "detail": "Servers were configured via ansible-playbook.", "match": "\\bansible-playbook\\b"}, {"id": "serverless", "tag": "LIVE", "title": "Deployed (Serverless Framework)", "detail": "A serverless stack was deployed.", "match": "\\b(serverless|sls)\\s+deploy\\b"}, {"id": "sst", "tag": "LIVE", "title": "Deployed / removed (SST)", "detail": "An SST stack was deployed or removed.", "match": "\\bsst\\s+(deploy|remove)\\b"}, {"id": "eas-expo", "tag": "LIVE", "title": "Published a mobile build (Expo/EAS)", "detail": "An Expo update or EAS build/submit ran.", "match": "\\beas\\s+(submit|build|update)\\b|\\bexpo\\s+publish\\b"}, {"id": "doctl", "tag": "LIVE", "title": "Changed DigitalOcean", "detail": "A DigitalOcean app deployment or droplet/k8s change ran.", "match": "\\bdoctl\\s+(apps\\s+create-deployment|kubernetes\\s+cluster\\s+(create|delete)|compute\\s+droplet\\s+(create|delete))\\b"}, {"id": "git-push-main", "tag": "LIVE", "title": "Pushed to a main branch", "detail": "Commits were pushed to a main/master/production branch.", "match": "\\bgit\\s+push\\b[^\\n]*\\b(origin\\s+)?(main|master|prod|production|release)\\b"}, {"id": "ngrok", "tag": "NETWORK", "title": "Opened a public tunnel (ngrok)", "detail": "A local service was exposed to the public internet.", "match": "\\bngrok\\b"}, {"id": "cloudflared", "tag": "NETWORK", "title": "Opened a Cloudflare tunnel", "detail": "A local service was exposed via a Cloudflare tunnel.", "match": "\\bcloudflared\\b"}, {"id": "localtunnel", "tag": "NETWORK", "title": "Opened a public tunnel", "detail": "A local service was exposed via a tunneling tool.", "match": "\\b(localtunnel|bore\\s+local|tailscale\\s+(funnel|serve))\\b"}, {"id": "socat", "tag": "NETWORK", "title": "Relayed traffic (socat)", "detail": "Traffic was relayed through socat.", "match": "\\bsocat\\b"}, {"id": "railway-connect", "tag": "NETWORK", "title": "Opened a DB proxy (Railway connect)", "detail": "Database access was routed through a temporary TCP proxy.", "match": "\\brailway\\s+connect\\b"}, {"id": "fly-proxy", "tag": "NETWORK", "title": "Opened a proxy (Fly.io)", "detail": "A proxy to a Fly.io service was opened.", "match": "\\bfly(ctl)?\\s+proxy\\b"}, {"id": "ssh-tunnel", "tag": "NETWORK", "title": "Opened an SSH tunnel", "detail": "Traffic was tunneled over SSH (-L/-R/-D).", "match": "(?:^|[\\s;&|])ssh\\s+[^\\n]*-[LRD]\\b", "caseSensitive": true}, {"id": "sql-priv", "tag": "SECURITY", "title": "Database role/grant changed", "detail": "A database role, user, or grant was created or altered.", "match": "\\b(CREATE\\s+ROLE|CREATE\\s+USER|DROP\\s+ROLE|GRANT\\b|REVOKE\\b|ALTER\\s+ROLE|DEFINE\\s+(USER|TOKEN|SCOPE|ACCESS))\\b", "multiline": true, "requiresDbClient": true}, {"id": "sql-destructive", "tag": "DATA", "title": "Destructive database change", "detail": "A table/database was dropped, truncated, or rows were deleted.", "match": "\\b(DROP\\s+(TABLE|DATABASE|SCHEMA)|TRUNCATE\\s+(TABLE\\s+)?|DELETE\\s+FROM)\\b", "multiline": true, "requiresDbClient": true}, {"id": "db-migrate", "tag": "DATA", "title": "Ran a database migration", "detail": "A schema migration was applied (or reset).", "match": "\\b(prisma\\s+migrate\\s+(deploy|reset)|drizzle-kit\\s+push|alembic\\s+(upgrade|downgrade)|rails\\s+db:migrate|knex\\s+migrate:(latest|up)|sequelize\\s+db:migrate|atlas\\s+migrate\\s+apply|migrate\\s+-path)\\b"}, {"id": "cloud-cred", "tag": "SECURITY", "title": "Configured cloud credentials", "detail": "Cloud CLI credentials were configured or logged in.", "match": "\\baws\\s+configure\\b|\\bgcloud\\s+auth\\s+(login|activate-service-account)\\b|\\baz\\s+login\\b|\\bdoctl\\s+auth\\s+init\\b"}, {"id": "auth-login", "tag": "SECURITY", "title": "Authenticated a CLI", "detail": "An authenticated login was performed.", "match": "\\bgh\\s+auth\\s+login\\b|\\bdocker\\s+login\\b|\\bnpm\\s+login\\b|\\bvercel\\s+login\\b|\\brailway\\s+login\\b|\\bnetlify\\s+login\\b|\\bwrangler\\s+login\\b"}, {"id": "key-create", "tag": "SECURITY", "title": "Created a key or token", "detail": "An access key, API key, or SSH key was generated.", "match": "\\bssh-keygen\\b|\\bgh\\s+secret\\s+set\\b|\\bopenssl\\s+(genrsa|genpkey|req\\s+[^\\n]*-keyout)\\b|\\b[a-z]+\\s+api-?keys?\\s+create\\b"}, {"id": "chmod-777", "tag": "SECURITY", "title": "Loosened file permissions (chmod 777)", "detail": "A path was made world-writable.", "match": "\\bchmod\\s+(-R\\s+)?0?777\\b"}, {"id": "env-write", "tag": "CONFIG", "title": "Wrote to an .env file", "detail": "Environment values were written to a local .env file.", "match": "(>>?|\\btee\\b)\\s*[\\w./-]*\\.env(\\.[\\w]+)?\\b"} ] }