harness: five new front-door fixtures, gitea's installer, HTTPS backends, per-file change names (R-462, R-624, R-735)
gates / gates (push) Successful in 2s
gates / gates (push) Successful in 2s
- fixtures (upgrade_fixtures_box.py): calibre-web (Upload form -> OPDS readback + the served EPUB), wger (web login -> weight entry API), crafty-controller (API v2 roles), uptime-kuma (socket.io polling: setup, login, addStatusPage -> public /api/status-page/<slug>); gitea posts its own first-run installer form (R-624's fixable case) and keeps the admin CLI for an installed one. calibre-web and wger run the template's own after_install on the bench, which has none. - R-735: the bench's `password:N:special` now has the controller's shape (randomWithSpecial); test seen failing first (length 32, no special), then 45/45. - upgrade_boxport / the memory watch: a backend traefik reaches over https (loadbalancer.server.scheme) is reached over https on the bench too (crafty-controller). - upgrade-test: files-before/after-detail.json and `files_changed_detail` NAME the files behind a files_may_change mark (R-734's method, now in the harness); test ChangedFiles. - test_catalog_gates: the gate count was stale (9, the runner has 10) and red on main; now 10. Evidence: felhom.eu/documentation/audits/more-night-apps-2026-09-30/ Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -442,6 +442,22 @@ class TestEnvBuilding(unittest.TestCase):
|
||||
import base64
|
||||
self.assertEqual(len(base64.b64decode(v[len("base64:"):])), 32)
|
||||
|
||||
def test_password_special_carries_the_controllers_shape(self):
|
||||
"""R-735: `password:N:special` must be what the controller's randomWithSpecial mints (deploy.go L1335):
|
||||
N long, a letter or digit first, at least one lower, upper, digit and one of `-_.!@#%+=`. Without the
|
||||
special character calibre-web's own rule refuses the password and the bench cannot seed the app.
|
||||
COMPANION RED-PROOF: before the fix `_gen` returned letters and digits only; this test failed."""
|
||||
felhom = "deploy_fields:\n - env_var: ADMIN_PASSWORD\n type: password\n generate: \"password:24:special\"\n"
|
||||
for _ in range(50):
|
||||
v = cvp.build_env("calibre-web", felhom, "${ADMIN_PASSWORD}")["ADMIN_PASSWORD"]
|
||||
self.assertEqual(len(v), 24, v)
|
||||
self.assertTrue(any(c in "-_.!@#%+=" for c in v), f"no special character: {v}")
|
||||
self.assertNotIn(v[0], "-_.!@#%+=")
|
||||
for cls in ("abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "0123456789"):
|
||||
self.assertTrue(any(c in cls for c in v), f"missing one of {cls[:3]}…: {v}")
|
||||
plain = "deploy_fields:\n - env_var: P\n type: password\n generate: \"password:16\"\n"
|
||||
self.assertTrue(cvp.build_env("x", plain, "${P}")["P"].isalnum()) # the plain form is unchanged
|
||||
|
||||
def test_deploy_fields_block_ends_at_the_next_top_level_key(self):
|
||||
felhom = "deploy_fields:\n - env_var: A\n type: text\napp_info:\n tagline: x\n"
|
||||
self.assertEqual([f["env_var"] for f in cvp.parse_deploy_fields(felhom)], ["A"])
|
||||
|
||||
Reference in New Issue
Block a user