test+docs: startup-refusal exit code, real-body 413, pre-1.1.0 migration note

- main() exits 2 on permissive config (not just the predicate)
- 413 proven with an actual over-limit wire body, not header-only
- README: machine-user accounts need a seeded state.json mapping; only
  granthi-sync-e2e required it in beta

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
Nirav Patel
2026-08-19 09:25:13 -04:00
co-authored by Claude Fable 5
parent 74d206cb4a
commit 14ccbd59f0
2 changed files with 38 additions and 0 deletions
+28
View File
@@ -364,6 +364,22 @@ class TestConfigPerms(unittest.TestCase):
err = granthi_link.check_config_perms(self.tmp.name, euid=not_me)
self.assertIn("owned by uid", err)
def test_main_exits_2_on_permissive_config(self):
"""The refusal must actually stop startup (exit nonzero), not just
return a string -- verified through main()."""
with open(self.tmp.name, "w") as f:
json.dump({"gitea_base": "http://x", "admin_token": "t",
"admin_login": "r", "admin_password": "p"}, f)
os.chmod(self.tmp.name, 0o644)
with mock.patch.object(granthi_link.sys, "argv",
["granthi_link.py", self.tmp.name]), \
mock.patch.object(granthi_link, "serve") as served, \
self.assertLogs("granthi-link", level="ERROR"):
with self.assertRaises(SystemExit) as cm:
granthi_link.main()
self.assertEqual(cm.exception.code, 2)
served.assert_not_called() # never reached serve()
class HandlerTestBase(ServiceTestBase):
def setUp(self):
@@ -397,6 +413,18 @@ class TestBodyLimits(HandlerTestBase):
self.assertEqual(status, 413)
self.assertIn("too large", resp["error"])
def test_oversized_real_body_413(self):
"""Send an actual over-limit payload on the wire (not just the
header), so the response is proven, not the predicate alone."""
body = json.dumps(
{"pad": "x" * (granthi_link.MAX_BODY_BYTES + 2000)}).encode()
self.assertGreater(len(body), granthi_link.MAX_BODY_BYTES)
status, resp = self.raw_post(
"/v1/link", body_bytes=body,
headers={"Content-Length": str(len(body)),
"Content-Type": "application/json"})
self.assertEqual(status, 413)
def test_missing_content_length_411(self):
status, _ = self.raw_post("/v1/link")
self.assertEqual(status, 411)