Support casework
Support casework.
Three documented problems, shown from report through resolution. Each case names where the evidence came from and what it can actually prove.
At a glance
- Three documented casesReal problems with evidence, decisions, and outcomes.
- Two synthetic workflow labsSafe environments for showing ticket, approval, and closure discipline, and for showing diagnosis held to evidence.
- What this demonstratesPatient troubleshooting, clear communication, and an honest handoff when ownership changes.
On this page
Case 1 / End-user investigation
Android device investigation
- Context and provenance
- A member's Android phone, described and documented in a published personal investigation. Not a customer device or a work assignment.
- Reported or observable problem
- The phone was showing unexpected pop-ups and faster-than-normal battery drain. The member could not say when it started or what they had installed.
- User or operator impact
- A non-technical user was uncomfortable using their own phone and could not tell what was safe to keep or remove.
- Initial questions
- What had changed recently. Whether any app was installed outside the Play Store. Whether the behavior was constant or triggered by specific actions.
- Investigation
- I isolated the device from other networks first, then used ADB to list installed packages and compared install timestamps against when the symptoms began, narrowing the search to one package.
- Finding
- The identified package matched known adware behavior. I reverse-engineered the APK with APKTool and JADX to see what it was actually doing, then correlated its indicators through VirusTotal and open-source research.
- Resolution
- Confirmed the package as the source, removed it, and explained in plain language what it had been doing and why it was unsafe to keep.
- Prevention and documentation
- Documented the investigation, including the identification method and the indicators found, in a published writeup. Identifiers and the sample itself stayed redacted.
- Customer-facing explanation
- "This app was reading more than it needed to and showing you ads based on that. I removed it and confirmed nothing else on your phone matches the same pattern."
- Engineering handoff
- Package name and install timestamp, ADB output, APKTool and JADX findings, and VirusTotal and OSINT correlation. Indicators and the sample were redacted for publication.
- Boundary
- This was a single consumer device investigated after the fact, not a live incident response engagement with logging or EDR already in place.
Source: the original writeup on Medium (opens in a new tab).
Case 2 / Personal integration case
Silent API write
- Context and provenance
- Personal project, verified against a live Wazuh manager as part of the Detection-as-Code Pipeline's deploy tooling. Not a customer ticket or a production incident.
- Reported or observable problem
- A PUT to update a rule file returned HTTP 200, the normal success code, but the file on the manager had not actually changed.
- User or operator impact
- Anyone trusting the status code alone would believe a rule update had deployed when it had not, leaving a stale detection rule in place.
- Initial questions
- Whether the request was reaching the manager at all. Whether the response body carried more information than the status code. Whether the condition was consistent or intermittent.
- Investigation
- I reproduced the call directly against the manager. The status code stayed 200 every time, but the response body reported error: 1, and the file content had not changed.
- Finding
- The write silently failed whenever the target filename already existed and the request omitted overwrite=true. The API accepted the request and returned success at the transport layer while rejecting it at the application layer.
- Resolution
- Added the explicit overwrite=true parameter, then added a post-write check that inspects the body-level error and total_failed_items fields rather than trusting the status code alone.
- Prevention and documentation
- Added a regression test that exercises this exact condition, documented it, and set deploy tooling to abort the rest of a reconciliation run on any body-level failure.
- Customer-facing explanation
- "I reproduced the issue. The request is completing at the HTTP layer, but the remote file is not changing. I am checking the response body and current state rather than repeating the same write. My next update will include either a verified change or the exact failure conditions needed for escalation."
- Engineering handoff
- Endpoint: PUT rule file, existing filename. Expected state: file updated, body reports success. Observed state: HTTP 200, body error: 1, file unchanged. Reproduction condition: overwrite=true omitted. Regression action: test added, deploy aborts on body-level failure.
- Boundary
- This is one deployment API's behavior in one project, not a general claim about REST API design. The regression test covers this specific condition, not the full space of partial-failure responses.
Source: Detection-as-Code Pipeline, threat model and deploy-rule test suite.
Case 3 / Personal systems case
Self-hosted access stack
- Context and provenance
- A self-hosted identity and deception lab I built and operate on my own hardware, a macOS host with a Linux virtual machine. Personal systems work, not a client environment.
- Reported or observable problem
- Container startup failures. The identity service and its database entered a permission loop under a mounted host volume, and one component had no published image for the machine's ARM64 architecture at all.
- User or operator impact
- As the only operator, any of these failures took the whole stack down until I fixed it. There was no one else to escalate to.
- Initial questions
- Whether the failure was the container image, the volume mount, or the host filesystem. Whether it was architecture-specific. Whether a dependency's expected input format had changed.
- Investigation
- I traced the permission loop to how the container image's user mapped onto a VirtioFS-backed host volume mount, and confirmed the missing image was an architecture gap by checking the registry directly for an AArch64 build.
- Finding
- Three separate root causes. Ownership mismatches between the container user and the mounted volume, no published AArch64 image for one component, and a cryptography library enforcing exact base64 padding and key-length constraints I had not matched.
- Resolution
- Adjusted volume ownership and mount handling, compiled the missing component natively for AArch64, corrected the key material to the exact length and padding the library expected, and reassigned colliding ports so every service could bind.
- Prevention and documentation
- Wrote setup and operating documentation covering each of these fixes so the stack rebuilds cleanly on either machine without re-diagnosing the same issues.
- Customer-facing explanation
- "The service wasn't starting because of how the container's file permissions and the host machine disagreed, not because of anything wrong with the data itself. I fixed the permission mapping and it starts clean now."
- Engineering handoff
- Alpine container UID or GID mismatch against a VirtioFS-backed bind mount. Missing arm64 image for one component, resolved with a native build. PyNaCl key-length and base64 padding mismatch at initialization. Two services requesting the same host port.
- Boundary
- This is a single self-hosted lab on personal hardware, not an enterprise identity platform or a production SSO deployment at any scale.
Source: Deceptive Identity Architecture project page.
Workflow lab
How I modeled a support workflow.
Scope Synthetic workflow lab, not a production ITSM deployment. Every user, device, alert, ticket, and approval in it is fictional.
I built Control Plane to work through the chain a support request actually travels, from the person reporting it to the evidence that closes it out, using open tooling rather than a commercial ITSM platform.
- Request Intake A request enters the system and gets a record.
- Identity Identity lookup The requester is resolved against a directory with roles and groups.
- MFA Multi-factor check Sensitive actions require a verified MFA enrollment, modeled with Keycloak TOTP.
- Endpoint state Device posture The requesting device's known state is checked before anything proceeds.
- Ticket Ticket and SLA The request becomes a tracked ticket against a service level.
- Approval Separation of duties A change requires approval from someone other than its requester. Self-approval is denied.
- Action Containment or change The approved action executes, such as an isolation or a remediation step.
- Evidence Closure evidence The case closes only against evidence in a hash-chained, append-only ledger.
Concepts modeled: joiner, mover, and leaver identity changes; ticket workflow and service levels; approval and separation of duties; change management; a knowledge base; device posture; and documented closure evidence. Source: Control Plane project page.
Workflow lab
How I modeled a diagnosis that has to prove itself.
Scope Synthetic SAML corpus against a self-hosted Keycloak identity provider, not a production IdP. Customer narratives are authored text standing in for real tickets, not real conversations.
A ticket that says sign-in is broken can have close to a dozen distinct causes that look identical from the person's chair, an expired certificate, a mismatched audience value, a stale attribute mapping. I built Assertion Desk to work through that ambiguity in order, and to make sure the answer handed back names the specific check that failed instead of a guess dressed up as confidence.
- Intake Custody and quarantine Artifacts are scanned for secret patterns before anything else touches them.
- Verify Deterministic checks Signature, audience, NameID, conditions, and clock skew are checked against the actual assertion.
- Extract Read the report The customer's own description is turned into structured facts: onset, recent change, what they believe is wrong.
- Draft Draft the explanation A summary and a root-cause explanation are drafted, grounded only in what the checks found.
- Gate Verify the explanation itself Every claim in the draft is checked against a verified finding, and a claim that points at a gap gets rejected.
- Decide Case disposition The outcome is computed from the checks and the grounding verdict, never from parsed model text.
- Approve Human review A person reviews the grounded draft and its evidence before anything is marked ready.
- Close Publish with evidence What ships names the specific check that failed and the artifact that proved it, not just that the case is resolved.
Concepts modeled: evidence custody ahead of investigation; deterministic checks ahead of generated explanations; a validator that rejects an unsupported claim before a human sees it; and closure evidence over a closure claim. Source: Assertion Desk project page.