Web applications, mobile apps, internal platforms, data pipelines, and replacing the system nobody wants to touch. The same engineers write penetration test findings, which is why the remediation line in those reports names a file and a change rather than a principle.
None of these are hard because of the framework. They are hard because of authorization, state, and the failure modes nobody writes down until the second incident.
Customer portals, partner dashboards, admin consoles. The role and object model is written before the first screen, enforced server side on every record, and covered by a test that fails the build when somebody adds an endpoint without a check.
Android and iOS. Keychain and Keystore for anything that persists, pinning where the threat model pays for the operational pain it causes, and a backend that never trusts the client's claim about which user is calling.
Approvals, reconciliation, case handling, fulfilment. Every state change attributable to a named human, timestamped, and reversible, because internal tools are where fraud and fat fingers both live.
Ingest, transform, serve. Jobs you can re-run safely, raw data kept so any day can be rebuilt from source, and schema contracts that break the pipeline loudly instead of quietly poisoning a dashboard for a month.
Payments, identity, CRM, logistics. Webhook signatures verified, idempotency keys on every write, retries with backoff, and a dead letter queue that someone is named as the owner of.
One capability moved at a time behind a routing layer, both systems live against the same data until the new path has carried real traffic long enough to be boring. Detail is further down this page.
The thing that goes wrong in software projects is not velocity. It is finding out in month five that what was built is not what was wanted, and that nobody could tell because nothing had been deployed.
Two to five working days. We write down the roles, the data we will hold and why, the deployment target, and what an attacker would want from it. It ends in a document short enough that you will read it and specific enough that you can disagree with it.
A thin slice running in your environment, behind real authentication, usually inside the first two weeks. Not a prototype on our laptop, not a click-through. From then on there is always something real to look at.
One to two week cycles against a branch you can pull and a deployment you can click. Each cycle ends with a short written note: what moved, what we got wrong, and what we are doing about it.
Five artifacts, listed below, plus one session in which your engineers deploy and roll back the system themselves while we sit there and do not touch the keyboard. If they cannot, it is not handed over.
We do not invoice for a status report. The cycle note is two paragraphs written by the engineer who did the work, and the deployed build is the real status.
The test of a build engagement is what happens six months after it ends, when the engineer maintaining it has never met us.
How to deploy, how to roll back, how to rotate every credential, which alarm means wake someone and which means wait until Monday. Written for the person who joins after we are gone.
Four to ten pages on the decisions and, more usefully, the options we rejected and why. Longer than that and nobody opens it, which makes it a liability rather than a document.
Data flows, trust boundaries, the abuse cases the design defends against, and the ones you consciously accepted. Hand it to whoever tests the system next and their first week gets considerably shorter.
Authorization tests per role, a negative test for every permission check, and integration tests across the paths that move money or personal data. We will not quote a coverage percentage as if it were a quality score.
Build, test, dependency audit, secret scan, deploy, roll back. Defined as code in your repository and runnable by someone who is not us, from a laptop that has never had our SSH key on it.
Repositories, cloud accounts, registrar, and app store listings in your organisation's name from the first commit. Our access is a set of invitations you can revoke in an afternoon.
Security is not a phase near the end, because the things that go wrong are structural and cost ten times more to change once there is data in the table. These five are settled in week one.
Broken object level authorization is the most common finding we write about other people's code. We would rather not write it about our own.
The role and object model is designed first and enforced in one place. An endpoint that checks the token but never checks whether this user owns that record is the single most common serious finding we report, and it is a design decision, not a bug.
Injected at runtime from AWS Secrets Manager, GCP Secret Manager, or Vault. History is scanned on every push, and a secret that does leak gets rotated, not quietly removed from the log.
Lockfiles pinned, an SBOM produced on each build, dependency audit and secret scan as pipeline stages that fail. A known-exploited vulnerability stops the deploy rather than opening a ticket nobody reads.
Who changed which record, when, from where, and what the previous value was, added at the same moment as the code that changes it. Retrofitted two weeks before an audit is how a field ends up null for the first eighteen months of its life.
A maintained identity provider or a maintained library. We do not hand-roll password hashing, session handling, TOTP, or a password reset flow, and we will argue about it if asked to.
The system is typically ten to twenty years old. Its author left. There are no tests, the schema encodes
three abandoned business models, and two columns named status and status_2 both
matter. Everybody wants it gone and nobody will touch it.
The plan that gets proposed is a clean rewrite with a cutover weekend. It means freezing every change your business needs for a year, racing a moving target, and betting the company on one Saturday night. We will not quote that plan.
A strangler migration instead: a routing layer in front of the old system, one bounded capability moved behind it at a time, both running against the same data until the new path has carried real traffic long enough to be uninteresting. Every route moved is value you keep. If the work stops at month four, you are four capabilities better off, not stranded between two half-systems.
Order matters: we move the capability with the clearest boundary first, not the one with the loudest complaints, because the first migration is also where we find out what the routing layer got wrong.
We read the existing code and write down what it actually does, including the behaviour that is accidental but that three departments now depend on. This is a priced piece of work with a document at the end, not a free discovery call.
Before anything moves, tests that pin the current behaviour, including the behaviour that is wrong. You cannot prove a migration is faithful against a system whose output nobody has ever recorded.
For the capabilities where correctness is expensive to get wrong, the new path runs in shadow against live traffic and we compare results before it serves a single user.
A route is not migrated until the old implementation is removed and the dead tables are dropped. Two live implementations of the same rule is how the data drifts apart.
Each of these has been offered. Each one ends badly in a way that is predictable from the first meeting.
If no one in your organisation can tell us what the current system does, that project has already failed and has not noticed yet. We will do the reading and write it down as a separate, priced piece of work, and you are free to take that document to another firm.
A fixed scope at a fixed price, or an open scope by the iteration. The third version, where the price is fixed and the scope is not, ends in a dispute about what was implied in a meeting. We have had that argument and we are not interested in it again.
If the only path to production runs through one of our engineers typing commands, it is not finished. Pipeline, rollback, and runbook are part of the build, not the line item that gets cut to hit a date.
No proprietary framework of ours in the middle, no infrastructure in our account, no credential you cannot rotate without calling us. There is no month of this engagement in which moving to another firm is impossible.
A report line that says to implement proper access control is written by someone who has never had to implement it in a system with twelve roles, a four-year-old permissions table, and a release on Thursday. When our report names the change, somebody on the team has made that change in production under that deadline.
It runs in the other direction too. Everything on this page is shaped by what we keep finding in other people's systems: the audit log added too late, the secret in the git history, the admin endpoint that checked the session and not the record.
TypeScript on the front end and in Node services, Python, Go, Postgres, containers on AWS or GCP, React Native or native Swift and Kotlin on mobile. If your stack is outside that list we will tell you so rather than bill you for our ramp-up. We will not learn a bespoke internal framework on your budget and then charge you for the time it took.
Two shapes. A fixed scope at a fixed price, written in enough detail that both sides know what is outside it. Or an iteration rate with a fixed cadence, which you can stop at the end of any cycle with nothing owed for the next one. The modelling phase is priced separately because it is useful to you even if you never hire us for the build.
We prefer it. Same repository, same review process, our commits reviewed by your people and theirs by ours. Handing over a system that nobody internally has ever reviewed is how a build becomes a dependency on us, which is the thing we are trying to avoid.
We will, and the report will state on the first page that we wrote the code, because that materially weakens it. A test by a firm with no stake in the result is worth more. Where you need that, hire someone else and we will hand them the threat model, the architecture notes, and source access so their time goes into testing rather than orientation.
One person who can decide what the software should do and is available for an hour a week, access to the systems it has to talk to, and whoever currently knows the most about the thing we are replacing for two or three sessions. Without the first of those, the project stalls regardless of how many engineers are on it.
Usually nothing, which is the point. If you want us to stay on for maintenance we will quote it as a separate agreement with a defined response window, not as a retainer that quietly renews. Either way the system runs without us on day one.
Manual testing across web, API, mobile, network, cloud, and LLM applications, with the exact change that closes each finding.
What happened, in what order, and what left the building. Evidence handled with chain of custody from the first image onward.
Agents with narrow tool permissions, a full log of every run, and the authorization boundary tested before it reaches your data.