DEV Community

Dakota Liu
Dakota Liu

Posted on

Probe Loopback First. Leave the Ticket Unwritten If /health Lies.

I will not publish a generated service until a local contract accepts the health body I actually received. A tidy README is not a running process. If /health lies, the ticket stays unwritten, and the bundle stays on disk.

Generated apps are cheap to start now. They are still easy to ship half-awake. Would you upload a tree because a draft looked finished, or because a loopback probe matched a file you froze first?

This is a from-zero tutorial for that second habit. Every stage has a command and a check you can rerun. Treat the samples as a local recipe, not as output copied from a remote host, and not as a benchmark.

What done means here

Done is four files and one decision record. The files are a contract, a stdlib server, a sealer, and a verifier. The record is publish_ticket.json, and it appears only after the probe matches.

Free model access can help you draft the handler. A free server option can later hold a bundle that already passed. I was given those two availability claims for this draft. They are not measurements, and they are not a promise about next month.

Disclosure: This article was prepared as part of MonkeyCode's product outreach.

I am not naming models, quotas, regions, or hardware. I am not saying how long a free slot lasts. If you care about those facts, read the current product docs and ignore any memory of an older limit. When this paragraph and the docs disagree, the docs win.

I am also not trying to prove a remote disk is empty. I am trying to prove that the process I might publish can answer a frozen contract on loopback. Those are different jobs. Mixing them is how a local pass gets narrated as a production fact.

Step 1: Freeze the contract before the handler

Create an empty directory and confirm the interpreter. I do not want a missing python3 to become an excuse to try the same check on a host I do not control.

mkdir -p healthgate && cd healthgate
python3 --version
Enter fullscreen mode Exit fullscreen mode

Verification: the shell prints a Python 3 version line. If it does not, stop and fix the local toolchain. Do not skip ahead to a publish step.

Now write health_contract.json. I keep the expected body tiny on purpose. A health route that needs a paragraph is already doing too much, and a status code alone will not catch a lying JSON object.

{
  "path": "/health",
  "bind_host": "127.0.0.1",
  "port": 8765,
  "timeout_seconds": 2,
  "max_body_bytes": 256,
  "required": {
    "status": "ok",
    "component": "healthgate"
  },
  "forbidden_keys": ["token", "password", "secret", "email"]
}
Enter fullscreen mode Exit fullscreen mode

Why ban those keys? A health document gets copied into logs, screenshots, and status pages. I do not want a generated handler to echo a credential because a prompt said to include debug context. Would you want that string in a screenshot later?

Check the file before you trust it:

python3 -c "import json; c=json.load(open('health_contract.json')); assert c['bind_host']=='127.0.0.1'; assert c['max_body_bytes']<=256; print('contract_ok', c['path'])"
Enter fullscreen mode Exit fullscreen mode

Verification: the command prints contract_ok /health. An assertion error means the contract drifted. Do not start the server yet. A running process against a bad contract is just a faster way to bless the wrong shape.

Step 2: Bind loopback and return only the required keys

The server below is a teaching stub. It is not a framework, and it is not a deploy script. It listens on 127.0.0.1, serves one path, and refuses to log request lines. Logging every hit is how a debug token leaks into a scrollback you later paste somewhere.

# serve_health.py
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import json

BODY = {"status": "ok", "component": "healthgate"}

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path != "/health":
            self.send_response(404)
            self.end_headers()
            return
        raw = json.dumps(BODY).encode("utf-8")
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(raw)))
        self.end_headers()
        self.wfile.write(raw)

    def log_message(self, fmt, *args):
        return

if __name__ == "__main__":
    ThreadingHTTPServer(("127.0.0.1", 8765), Handler).serve_forever()
Enter fullscreen mode Exit fullscreen mode

Start it in one terminal with python3 serve_health.py. In a second terminal, read the body yourself:

python3 -c "import urllib.request; print(urllib.request.urlopen('http://127.0.0.1:8765/health', timeout=2).read().decode())"
Enter fullscreen mode Exit fullscreen mode

Verification: you should see a JSON object with status and component only. Connection refused means the process is down. Extra keys mean the stub drifted from the contract. Fix either problem before a ticket exists.

A model draft can type this file faster than I can. I would still run the probe myself. A suggested handler is text. A probe is a socket. Which one are you actually publishing?

Step 3: Seal an allowlist, not the working tree

I copy named files into bundle/. I do not archive the directory I am editing. Scratch notes, .env files, and editor backups do not get a free ride because they sat beside the server. Have you ever zipped a repo just to try a host, then remembered a scratch file was in there?

# seal_bundle.py
import shutil
from pathlib import Path

ALLOW = ["health_contract.json", "serve_health.py", "verify_health.py"]
root = Path("bundle")
if root.exists():
    shutil.rmtree(root)
root.mkdir()
for name in ALLOW:
    src = Path(name)
    if not src.is_file():
        raise SystemExit(f"missing:{name}")
    shutil.copy2(src, root / name)
print("sealed", len(ALLOW))
Enter fullscreen mode Exit fullscreen mode

Run this before verify_health.py exists. It should fail. That failure is the check. A partial bundle is not a bundle, and a sealer that skips missing files will quietly publish an older tree.

python3 seal_bundle.py
Enter fullscreen mode Exit fullscreen mode

Verification now: the exit code is non-zero and the message starts with missing:. After step 4, rerun the sealer and list the tree.

python3 seal_bundle.py
find bundle -type f | sort
Enter fullscreen mode Exit fullscreen mode

Verification later: exactly three files, no dotfiles, and no ticket inside bundle/. The ticket is a local decision. Shipping it as application content would confuse a host into thinking a pass is a route. I want the host, if I use one at all, to receive the program, not my grade sheet.

Step 4: Parse the body and fail closed

The verifier does not start your server. You already did that. It reads the contract, refuses any bind host other than loopback before it opens a socket, then GETs the path. Forbidden keys fail first. Value mismatches fail next. Extra keys fail last. A huge body cannot sneak through as a pass, because the read is capped and an oversize buffer is a failure.

# verify_health.py
import hashlib, json, sys, urllib.request
from pathlib import Path

c = json.loads(Path("health_contract.json").read_text())
if c["bind_host"] != "127.0.0.1":
    sys.exit("refusing_non_loopback")
url = f"http://{c['bind_host']}:{c['port']}{c['path']}"
try:
    with urllib.request.urlopen(url, timeout=c["timeout_seconds"]) as resp:
        raw = resp.read(c["max_body_bytes"] + 1)
        code = resp.status
except Exception as exc:
    sys.exit(f"probe_failed:{type(exc).__name__}")
if code != 200 or len(raw) > c["max_body_bytes"]:
    sys.exit("bad_status_or_size")
try:
    body = json.loads(raw.decode("utf-8"))
except json.JSONDecodeError:
    sys.exit("not_json")
if not isinstance(body, dict):
    sys.exit("not_object")
for key in c["forbidden_keys"]:
    if key in body:
        sys.exit(f"forbidden:{key}")
for key, value in c["required"].items():
    if body.get(key) != value:
        sys.exit(f"mismatch:{key}")
if set(body) != set(c["required"]):
    sys.exit("unexpected_keys")
ticket = {
    "decision": "local_pass",
    "url": url,
    "sha256": hashlib.sha256(raw).hexdigest(),
    "body_bytes": len(raw),
}
Path("publish_ticket.json").write_text(json.dumps(ticket, indent=2) + "\n")
print("ticket_written", ticket["sha256"][:12])
Enter fullscreen mode Exit fullscreen mode

urlopen raises on many HTTP errors, so a wrong path often shows up as probe_failed rather than a polite 404. That is fine for this gate. I would rather see a hard miss than a parser that tries to interpret an error page as health.

With the server still running, write the ticket and read it back:

python3 verify_health.py
python3 -c "import json; t=json.load(open('publish_ticket.json')); assert t['decision']=='local_pass'; print('ticket_ok', t['body_bytes'])"
Enter fullscreen mode Exit fullscreen mode

Verification: one line starting with ticket_written, then ticket_ok and a byte count no higher than 256. The hash is an integrity note for the bytes you just probed. It is not a signature, and it is not authentication. Do not describe it as either.

Stop the server and probe again. I expect probe_failed and a non-zero exit. Delete a stale ticket when the probe fails. Otherwise yesterday's pass pretends to bless today's crash.

python3 verify_health.py || rm -f publish_ticket.json
test ! -f publish_ticket.json && echo "ticket_absent_after_failure"
Enter fullscreen mode Exit fullscreen mode

Verification: ticket_absent_after_failure prints, and publish_ticket.json is gone. If the file remains, you did not fail closed. Do not talk yourself into uploading anyway.

Step 5: Only then ask whether a host is relevant

I use a short table so the publish decision stays boring. Boring is what I want. Excitement belongs in the product, not in the gate.

Check Pass Fail
Ticket decision is local_pass Do not upload
Bundle list allowlist only Reseal and reprobe
Body hash matches the ticket Delete the ticket
Bind host still 127.0.0.1 in the contract Refuse the probe

A drafting model fits earlier, while serve_health.py is still text on disk. It is a weak fit for the question "should I publish?" once you have skipped the probe. Why spend a free call to narrate a check your terminal can already fail?

A free server option is a possible later place for bundle/, and only if today's terms still cover this kind of toy process. I have not measured that option. I am not claiming it is empty, fast, permanent, or the right host for anything with real users. If the terms changed, the local ticket is still useful and the upload is not.

If the ticket is green and you want a next read, open the current MonkeyCode notes on free model access and the free server option, then decide whether this sealed stub belongs there at all. Skip the product if the docs do not match the job. The gate does not need a logo to fail a bad body.

Limits, and who should walk away

Loopback success does not prove TLS, DNS, idle cutoff, or disk survival on any host. The forbidden-key list is not a secret scanner. It will miss a key named api_key unless you add it. Add it if your drafts keep inventing that name. Do not put customer data in /health and then congratulate the contract.

Skip this approach when the process cannot bind 127.0.0.1 for a check, or when health output must vary per request. Skip it for multi-service setups, meshes, and anything that needs a formal change approval. A three-file Python gate will feel strict and still be the wrong control. Use the pipeline you already trust.

I am also not giving you a latency number. A number from a laptop would be folklore by the time you read it. The artifact is the exit code, not a chart. If someone asks how fast the free host was, the honest answer from this page is: I did not measure it.

Rehearse the lie

Change BODY so it includes "token": "demo". Restart the server. Run the verifier. You want forbidden:token, a non-zero exit, and no fresh ticket. Put the body back afterward. Then add "build": "local" and confirm that unexpected keys fail too.

python3 verify_health.py; echo "exit:$?"
Enter fullscreen mode Exit fullscreen mode

If that exit were zero while a token sat in the JSON, would you still publish? I would not. The host is optional. The match is the point. Rehearse the failure once before you trust the success path, because a gate you have never seen fail is just a script you hope works.

Close the loop

Freeze the contract. Bind loopback. Seal named files. Write the ticket only when the body matches, and leave it unwritten when the probe fails. A draft from anywhere is still text until the probe runs. A host, free or paid, does not get to overrule a health body that does not parse.

Top comments (0)