Portcall
A pre-deployment network check in TypeScript — one command that tells a stranger's network whether the tool will run there.
LEVEL 1THE PROBLEM
A deployment into a customer's environment fails on the network far more often than it fails on the software, and it fails after everyone is already on the call. Their resolver sinkholes a hostname. An intercepting proxy nobody mentioned demands auth. A corporate root re-signs every certificate the tool tries to pin. Each of those is a different team and a different ticket, and the tool reports all of them as the same unhelpful timeout. I have spent four years on the customer side of exactly this conversation. Portcall is the artifact I wanted to be able to send ahead of the first call: one command a platform or security team runs inside their own network, before anything is deployed, that answers whether an AI developer tool can work there — and if not, names the layer that is blocking it and what has to change.
LEVEL 2THE BUILD
A single-command TypeScript CLI with three runtime dependencies and no install step, driven entirely by a declared profile: the hosts and endpoints a tool needs, written down as YAML rather than compiled in, so the same binary can vouch for a tool it has never heard of. Five probes run in a fixed order, and the order is the argument: `dns` first, because a name that does not resolve makes every connection result after it meaningless; `egress` second, attempting resolve, TCP connect, TLS and a GET, and naming which of those layers stopped it; `proxy` third, because an intermediary demanding auth explains the egress blockers reported one probe earlier; `tls` fourth, capturing the chain through whichever proxy the environment names and evaluating it for interception, so a reader meets the intermediary before the certificate it presents; and `truststore` last, because it reads the anchors `tls` observed and answers the question they raise — does anything on this machine actually trust them, and does every runtime on it see the same answer. A failure portcall cannot classify is reported as `unclassified` at severity `unknown` rather than guessed at. Findings render as text, JSON or HTML through a redaction boundary, so a report can be handed to a vendor when the hostnames cannot.
BOSS FIGHTTHE RESULT
Feature-complete: every milestone from M0 to M5 landed. The CLI, the profile loader, the finding model, the three renderers and the redaction boundary shipped in M0; all five probes - `dns`, `egress`, `proxy`, `tls`, `truststore` - are registered and run in the fixed order the argument requires, with the TLS probe verified against a real MITM proxy in a docker-compose hostile-network harness rather than against a mock, and a committed fixture per failure class holding the classification matrix in place, because the whole value of the tool is that it names the right layer. M4 landed the `truststore` probe and the cross-check between a root observed intercepting traffic and the stores each runtime actually loads, proven against a real corporate root on macOS, Windows and Linux, hand-rolled Java keystore reader included - the case where the browser trusts the corporate root and Node does not, which is the failure that wastes an afternoon. M5 was packaging: named profiles for Anthropic Claude Code and Cursor beside the generic one, held current by a freshness test rather than by good intentions; a `SHA256SUMS` manifest signed through Sigstore keyless signing, verified inside the release workflow before anything publishes; and a one-command demo that has to exit 2 against the hostile harness before CI will render the recording, so a broken demo reddens the build instead of producing a polished capture of a failure. `v0.1.0-rc.1` is tagged. The edges are written down rather than papered over: the released executables stay unsigned until v2 - it is the manifest that is signed, not the binary - and portcall is not a security scanner, not a general network troubleshooter, and does no SSO round trip or endpoint-policy check. Everything it reports is anchored to a profile.
HIGH SCORES
- 5PROBES REGISTEREDDNS · EGRESS · PROXY · TLS · TRUSTSTORE
- 859TEST CASESVITEST · 49 FILES · 0 FAILING
- 3VENDOR PROFILESGENERIC · CLAUDE CODE · CURSOR
- 3REPORT FORMATSTEXT · JSON · HTML
- 0BYTES UPLOADEDNO TELEMETRY · REPORT STAYS PUT
- 48ADRSDECISIONS RECORDED