Malformed external data
- Control
- Strict schema validation before business logic
- Residual risk
- Valid but incorrect source data still needs business review.
Names, identifiers, exact field mappings, volumes, and proprietary integration contracts are generalized.
Moved employee onboarding from repeated manual PII handling to a validated, minimized, least-privilege automation pipeline.

HR Source selected.
Every new hire generated sensitive identity, document, and banking data that had to reach several internal systems before day one.
Repeated manual entry made the process slow and expanded the number of intermediate PII copies. The pipeline needed to reduce handling without turning the automation layer into a new shadow database.
End-to-end automation of Hyundai's employee onboarding flow, built at Way-V. Every new hire generates a burst of sensitive data - full name, national ID (CPF), personal documents, banking details - that must land in multiple internal systems (HR, payroll, access management) before day one. Part of that flow was manual: PII copied between spreadsheets, forms, and systems. A security problem wearing an efficiency costume.
THREAT MODEL FIRST - Before writing integration code, the question was: how does this pipeline fail, and what does it expose when it does? The controls weren't a compliance checklist bolted on at the end - they were the architecture.
THE CONTROLS - All external input treated as hostile: schema validation, type checking, and sanitization at the edge before anything touches business logic. Documents in private S3 buckets with encryption at rest, accessed through a service-specific least-privilege IAM role - never user-bound credentials. Data minimization per integration: each destination system receives only the fields it actually needs, so a system that needs name and employee ID never sees CPF or banking data. Integrations exclusively through authenticated APIs with defined contracts - never direct database access. Secrets injected via environment configuration, never in code or Git history. PII-masked structured logging: full operational traceability without the logs becoming a shadow database of personal data. Generic external errors (internal detail goes to internal logs - error messages are free reconnaissance otherwise). Idempotent critical operations, because retries are not optional and a duplicated employee record is a second, unmanaged copy of someone's PII.
RESULTS - Onboarding went from a multi-day manual process to an automated, consistent, traceable pipeline. PII stopped circulating through spreadsheets, intermediate copies dropped sharply, and each system's access shrank to exactly what its function required. Zero data exposure incidents across the period I operated it.
No control is presented as total risk elimination.
Build a payload for purpose, not convenience.
Keep ownership with each destination.
Keep internal detail out of client-facing errors.
01# Every external input is hostile until proven otherwise.02import structlog, boto303from pydantic import BaseModel, field_validator04 05log = structlog.get_logger()06sts = boto3.client("sts")07 08class NewHire(BaseModel):09 """Edge schema - validation runs BEFORE anything touches business logic."""10 full_name: str11 cpf: str # Brazilian national ID - never logged in clear12 bank_account: str13 14 @field_validator("cpf")15 @classmethod16 def valid_cpf(cls, v: str) -> str:17 if not _cpf_check_digits(v):18 raise ValueError("invalid_cpf") # generic - no reconnaissance leak19 return v20 21def _mask(cpf: str) -> str:22 return f"***.***.***-{cpf[-2:]}" # PII-masked structured logging23 24def onboard(raw: dict) -> None:25 hire = NewHire.model_validate(raw) # rejects malformed input at the edge26 log.info("onboarding.start", cpf=_mask(hire.cpf))27 28 # Service-specific, least-privilege role - short-lived, never user-bound creds.29 creds = sts.assume_role(30 RoleArn="arn:aws:iam::****:role/onboarding-writer",31 RoleSessionName="onboarding",32 DurationSeconds=900, # auto-expiring session33 )["Credentials"]34 35 # Data minimization: payroll gets name + employee_id, never CPF or banking.36 payroll.push(name=hire.full_name, employee_id=_derive_id(hire), creds=creds)Validate at the edge, assume a short-lived least-privilege role, mask PII in logs.
The stable operation identity maps the retry to the existing workflow.
Other completed steps remain recorded while the failed integration stays retryable.
Multi-day manual handling became an automated and traceable workflow
PII stopped circulating through repeated spreadsheet copies
Each integration received only the fields required for its function