ansible-automation-eng…
Ansible automation: playbooks, roles, collections, Molecule testing, Vault security.
Load when reviewing code that handles personal data in logs, test fixtures, error responses, serialized output, URLs, telemetry, or git history.
$ npx -y skills add notque/vexjoy-agent --agent claude-codeHow it fires
How this agent gets triggered: by you, by Claude, or both.
Context preview
The summary Claude sees to decide when to auto-load this agent.
Load when reviewing code that handles personal data in logs, test fixtures, error responses, serialized output, URLs, telemetry, or git history.
Load when reviewing code that handles personal data in logs, test fixtures, error responses, serialized output, URLs, telemetry, or git history.
PII exposure: personally identifiable information appears in a context with broader visibility, longer retention, or lower trust than intended. Use synthetic data in tests, structured identifiers in logs, explicit field selection in API responses.
---
Tests, fixtures, snapshots, cassettes, and seed files must use obviously synthetic identifiers.
**Python:**
fixture = {
"email": "user@example.com",
"org_slug": "org-slug",
"name": "Jane Doe",
"ip": "198.51.100.23", # RFC 5737
"arr_usd": 120000,
"renewal_date": "2026-01-01",
}**TypeScript:**
const fixture = {
email: 'user@example.com',
orgSlug: 'org-slug',
name: 'John Doe',
ip: '203.0.113.42', // RFC 5737 TEST-NET-3
monthlySpend: 1000,
seatCount: 25,
};| Type | Safe Values | Standard | |------|-------------|----------| | Email domains | `example.com`, `example.org`, `example.net`, `.invalid` | RFC 2606 | | IPv4 | `192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24` | RFC 5737 | | IPv6 | `2001:db8::/32` | RFC 3849 | | Names | `Jane Doe`, `John Doe`, `Alice`, `Bob`, `Acme Corp` | Convention |
Real data in git history cannot be fully purged. A single real email is a GDPR data subject access request waiting to happen.
rg -n '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' tests/ fixtures/ --type py --type ts | \
rg -v 'example\.(com|org|net)|noreply|test@|foo@|user@'
rg -n '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b' tests/ fixtures/ | \
rg -v '192\.0\.2\.|198\.51\.100\.|203\.0\.113\.|127\.0\.0\.|0\.0\.0\.0|10\.\|172\.(1[6-9]|2|3[01])\.|192\.168\.'
rg -n 'customer|account.*slug|org.*slug|tenant' tests/ fixtures/ --type py --type ts---
Log internal ID, salted hash, or correlation ID — never raw email, IP, phone, or request body.
**Python:**
import hashlib
def hash_email(email: str) -> str:
return hashlib.sha256(f"salt:{email}".encode()).hexdigest()[:12]
logger.warning(
"identity lookup failed",
extra={"user_id": user.id, "email_hash": hash_email(user.email)},
)**TypeScript:**
logger.warn('signup failed', {
userId: user.id,
reason: 'validation_failed',
});**Go:**
slog.Warn("identity lookup failed",
"user_id", user.ID,
"error", err,
)PII in logs creates a secondary data store bypassing access controls. Log aggregators retain data for months, index for full-text search, and expose to broad teams.
rg -n 'logger\.\w+\(.*email|logger\.\w+\(.*REMOTE_ADDR|logger\.\w+\(.*request\.(body|data|META)' --type py rg -n 'logger\.\w+\(.*email|logger\.\w+\(.*req\.(body|ip)|console\.\w+\(.*email' --type ts rg -n 'set_user\(|set_tag\(.*email|set_extra\(.*email' --type py rg -n 'slog\.\w+\(.*email|log\.\w+\(.*email|zap\.\w+\(.*email' --type go
---
Emails, phone numbers, names in URLs appear in browser history, server logs, CDN logs, referrer headers, analytics.
**Python:**
request.session["login_error"] = "invalid_magic_code"
return redirect("/login/error")**TypeScript:**
return redirect('/oauth/error?reason=invalid_code');rg -n 'redirect.*email=|redirect.*user=|redirect.*phone=' --type py --type ts rg -n 'f".*\?.*email|`.*\?.*email|\?.*email=' --type py --type ts
---
Declare explicit field lists excluding PII not required by the caller.
**Python (DRF):**
class UserPublicSerializer(ModelSerializer):
class Meta:
model = User
fields = ['id', 'display_name', 'avatar_url']**TypeScript (Prisma):**
const user = await prisma.user.findUnique({
where: { id },
select: { id: true, displayName: true, avatarUrl: true },
});
return res.json(user);**GraphQL:**
type UserPublic {
id: ID!
displayName: String!
avatarUrl: String
}`fields = '__all__'` exposes every column including fields added by future migrations. Full-row Prisma queries return password hashes, 2FA secrets.
rg -n "fields = '__all__'" --type py
rg -n 'email|phone|ipAddress|password' --type graphql --type ts | rg 'type |interface '
rg -n 'findUnique\(|findFirst\(' --type ts | rg -v 'select:'---
Error responses: generic message + correlation ID. Stack traces, SQL, request bodies stay server-side.
**Python:**
import uuid
@app.errorhandler(Exception)
def handle_error(error):
correlation_id = str(uuid.uuid4())
app.logger.error("unhandled exception",
extra={"correlation_id": correlation_id, "error": str(error)}, exc_info=True)
return {"error": "internal server error", "reference": correlation_id}, 500**TypeScript:**
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
const correlationId = crypto.randomUUID();
console.error({ correlationId, error: err.stack });
res.status(500).json({ error: 'internal server error', reference: correlationId });
});rg -n 'err\.stack|error\.stack|traceback|exc_info' --type py --type ts | rg -v 'logger\.|console\.'
rg -n 'request\.(body|data|form)|req\.body' --type py --type ts | rg 'return |res\.(json|send)'
rg -n 'set_user\(|set_context\(|set_extra\(' --type py | rg 'email|phone|ip|address'---
# Email addresses (excluding safe domains) rg -n '[a-zA-Z0-9._%+-]+@
Essays and writing behind this toolkit live at vexjoy.com. VexJoy Agent connects plain-English requests to specialist agents, skills, and workflows. /do selects the knowledge and tools needed for your task.
Repo: notque/vexjoy-agent
Ansible automation: playbooks, roles, collections, Molecule testing, Vault security.
**Scope**: Module selection patterns, builtin vs command/shell decisions, collection modules, and version-specific module changes **Version range**:…
**Scope**: Molecule test scenarios, ansible-lint rules, idempotency validation, and check-mode patterns **Version range**: Molecule 6.0+ / ansible-lint 6.0+ /…
Universal rules injected by /do at dispatch. Each agent's .md file supplies domain rules.
**Scope**: Failure modes in agent output style — over-reporting, self-congratulation, verbose narration, and hedging. Covers what to detect and how to fix…
Zero-dependency combat visual upgrades: CSS particle replacement, Framer Motion combat juice, CSS 3D card transforms.