diff --git a/runtime/history/NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191.json b/runtime/history/NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191.json new file mode 100644 index 00000000..85c7d392 --- /dev/null +++ b/runtime/history/NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191.json @@ -0,0 +1,38 @@ +{ + "schema_version": 1, + "channel": "homelab-runtime", + "command_id": "NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191", + "status": "FAIL", + "rc": 3, + "host": "pve01", + "mode": "read-only", + "component": "newfi-newfdom-telegram214-netbird-usa-forwarded-agent-readonly", + "started_at_utc": "2026-09-19T23:57:09Z", + "finished_at_utc": "2026-09-19T23:57:13Z", + "reference_register_checked": true, + "reference_sha256": "5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66", + "error_register_checked": true, + "error_register_sha256": "3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0", + "command_sha256": "7c3dadf65cc5f836859b5a49c0eb69fee72025b4bb20a86ea2e284e25188e1a1", + "duplicate_failed_command_blocked": false, + "block_reason": null, + "execution_started": true, + "change_declared": false, + "result_contract_valid": true, + "result_contract_status": null, + "result_contract_error": null, + "command_rc": 3, + "changes_made": false, + "rollback_started": false, + "rollback_restored": null, + "mutation_outcome": "NO_MUTATION", + "sanitized": true, + "secrets_included": false, + "private_addresses_included": false, + "raw_evidence_retained_locally": true, + "raw_evidence_sha256": "d5c2a115ff45953643648838f19d31a0b2b7b4c6e1a1a142dead7e426fe2a533", + "sanitized_output_sha256": "d5c2a115ff45953643648838f19d31a0b2b7b4c6e1a1a142dead7e426fe2a533", + "output_truncated_in_json": false, + "full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt", + "output": "NEWFI191_AUTH={\"command_id\":\"NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191\",\"decision\":\"HOLD_USA_NETBIRD_FORWARDED_AGENT_TELEGRAM_EGRESS\",\"error_code\":\"SSH_AUTH_DENIED\",\"forwarded_agent\":{\"fingerprints\":[\"SHA256:JMCyBDSD7PKqwwKndzDGAO4Lgm55nEmec9Ssn6QGtKg\",\"SHA256:tfEP9WF58ZcGe5zL/juscxX/sVAeS6fxwwiPjpj2I5U\",\"SHA256:PS+jG8Qun3vviOwZ4A2/ozwro+Jeav/x9VkfvH/d2yI\"],\"present\":true,\"ssh_add_rc\":0},\"hostkey\":{\"expected_match\":true,\"fingerprints\":[\"SHA256:J/5Kp48TdNA/RdlTFGEX4nr71yM6uc5ub5Iahr4xAWE\",\"SHA256:nen1KYo/PIGw45nlakIZpa/SSo/llm3tokCz0hFzboE\",\"SHA256:DXJGwunC5tEVvnC3nRxyayTN8FXmyJcVgf+Oa6udQsY\"]},\"relay\":{\"connection_type\":\"P2P\",\"name\":\"relay.netbird.selfhosted\",\"netbird_ip_sha256\":\"0f61feb58699a097fdfae741ce53e84cd9eae29e8c8d893a0822f20af9231d4c\",\"status\":\"Connected\",\"usa_public_endpoint_confirmed\":true},\"ssh\":{\"accepted_fingerprints\":[],\"error_class\":\"AUTH_DENIED\",\"offered_fingerprints\":[\"SHA256:JMCyBDSD7PKqwwKndzDGAO4Lgm55nEmec9Ssn6QGtKg\",\"SHA256:tfEP9WF58ZcGe5zL/juscxX/sVAeS6fxwwiPjpj2I5U\",\"SHA256:PS+jG8Qun3vviOwZ4A2/ozwro+Jeav/x9VkfvH/d2yI\"],\"rc\":255,\"stderr_sha256\":\"96e972784f367ad113bee81e15345cf73d3a15b106f5857a98cfedf2074363a2\",\"stdout_sha256\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"},\"status\":\"FAIL\",\"tcp22\":true}\nHOMELAB_RESULT_CONTRACT={\"version\":1,\"command_id\":\"NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191\",\"status\":\"FAIL\",\"changes_made\":false,\"rollback_started\":false,\"rollback_restored\":null}\n" +} diff --git a/runtime/history/NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191.txt b/runtime/history/NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191.txt new file mode 100644 index 00000000..ccbfa7ca --- /dev/null +++ b/runtime/history/NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191.txt @@ -0,0 +1,34 @@ +CHAT_OUTPUT_BEGIN +COMMAND_ID=NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191 +STATUS=FAIL +RC=3 +HOST=pve01 +MODE=read-only +COMPONENT=newfi-newfdom-telegram214-netbird-usa-forwarded-agent-readonly +REFERENCE_REGISTER_CHECK=OK +REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66 +ERROR_REGISTER_CHECK=OK +ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0 +COMMAND_SHA256=7c3dadf65cc5f836859b5a49c0eb69fee72025b4bb20a86ea2e284e25188e1a1 +DUPLICATE_FAILED_COMMAND_BLOCKED=false +EXECUTION_STARTED=true +CHANGE_DECLARED=false +RESULT_CONTRACT_VALID=true +RESULT_CONTRACT_STATUS=NOT_APPLICABLE +RESULT_CONTRACT_ERROR=NONE +COMMAND_RC=3 +CHANGES_MADE=false +ROLLBACK_STARTED=false +ROLLBACK_RESTORED=null +MUTATION_OUTCOME=NO_MUTATION +SANITIZED=yes +SECRETS_INCLUDED=no +PRIVATE_ADDRESSES_INCLUDED=no +RAW_EVIDENCE_SHA256=d5c2a115ff45953643648838f19d31a0b2b7b4c6e1a1a142dead7e426fe2a533 +SANITIZED_OUTPUT_SHA256=d5c2a115ff45953643648838f19d31a0b2b7b4c6e1a1a142dead7e426fe2a533 +OUTPUT_BEGIN +NEWFI191_AUTH={"command_id":"NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191","decision":"HOLD_USA_NETBIRD_FORWARDED_AGENT_TELEGRAM_EGRESS","error_code":"SSH_AUTH_DENIED","forwarded_agent":{"fingerprints":["SHA256:JMCyBDSD7PKqwwKndzDGAO4Lgm55nEmec9Ssn6QGtKg","SHA256:tfEP9WF58ZcGe5zL/juscxX/sVAeS6fxwwiPjpj2I5U","SHA256:PS+jG8Qun3vviOwZ4A2/ozwro+Jeav/x9VkfvH/d2yI"],"present":true,"ssh_add_rc":0},"hostkey":{"expected_match":true,"fingerprints":["SHA256:J/5Kp48TdNA/RdlTFGEX4nr71yM6uc5ub5Iahr4xAWE","SHA256:nen1KYo/PIGw45nlakIZpa/SSo/llm3tokCz0hFzboE","SHA256:DXJGwunC5tEVvnC3nRxyayTN8FXmyJcVgf+Oa6udQsY"]},"relay":{"connection_type":"P2P","name":"relay.netbird.selfhosted","netbird_ip_sha256":"0f61feb58699a097fdfae741ce53e84cd9eae29e8c8d893a0822f20af9231d4c","status":"Connected","usa_public_endpoint_confirmed":true},"ssh":{"accepted_fingerprints":[],"error_class":"AUTH_DENIED","offered_fingerprints":["SHA256:JMCyBDSD7PKqwwKndzDGAO4Lgm55nEmec9Ssn6QGtKg","SHA256:tfEP9WF58ZcGe5zL/juscxX/sVAeS6fxwwiPjpj2I5U","SHA256:PS+jG8Qun3vviOwZ4A2/ozwro+Jeav/x9VkfvH/d2yI"],"rc":255,"stderr_sha256":"96e972784f367ad113bee81e15345cf73d3a15b106f5857a98cfedf2074363a2","stdout_sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},"status":"FAIL","tcp22":true} +HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191","status":"FAIL","changes_made":false,"rollback_started":false,"rollback_restored":null} + +OUTPUT_END +CHAT_OUTPUT_END diff --git a/runtime/latest.json b/runtime/latest.json index 6d2d1769..85c7d392 100644 --- a/runtime/latest.json +++ b/runtime/latest.json @@ -1,19 +1,19 @@ { "schema_version": 1, "channel": "homelab-runtime", - "command_id": "SUPPORT-260920-PVEPRO-V1-BASELINE-CONTINUATION-READONLY-720R1", - "status": "OK", - "rc": 0, + "command_id": "NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191", + "status": "FAIL", + "rc": 3, "host": "pve01", "mode": "read-only", - "component": "pvepro-v1-baseline-continuation-readonly", - "started_at_utc": "2026-09-19T23:55:44Z", - "finished_at_utc": "2026-09-19T23:55:46Z", + "component": "newfi-newfdom-telegram214-netbird-usa-forwarded-agent-readonly", + "started_at_utc": "2026-09-19T23:57:09Z", + "finished_at_utc": "2026-09-19T23:57:13Z", "reference_register_checked": true, "reference_sha256": "5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66", "error_register_checked": true, "error_register_sha256": "3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0", - "command_sha256": "5db057f95eaa17a2cd9dc6f722baa09e278b07f4fbf4cbed1e3f42744e7e4284", + "command_sha256": "7c3dadf65cc5f836859b5a49c0eb69fee72025b4bb20a86ea2e284e25188e1a1", "duplicate_failed_command_blocked": false, "block_reason": null, "execution_started": true, @@ -21,7 +21,7 @@ "result_contract_valid": true, "result_contract_status": null, "result_contract_error": null, - "command_rc": 0, + "command_rc": 3, "changes_made": false, "rollback_started": false, "rollback_restored": null, @@ -30,9 +30,9 @@ "secrets_included": false, "private_addresses_included": false, "raw_evidence_retained_locally": true, - "raw_evidence_sha256": "a4ad6491e8a0664a5f0442b527233e5f256a690a536b23ee0f3d69e4b4620992", - "sanitized_output_sha256": "4fba74cd84c317cf0136858f3d64fa80f38be851347aac3bc79216fdbdc7abe4", + "raw_evidence_sha256": "d5c2a115ff45953643648838f19d31a0b2b7b4c6e1a1a142dead7e426fe2a533", + "sanitized_output_sha256": "d5c2a115ff45953643648838f19d31a0b2b7b4c6e1a1a142dead7e426fe2a533", "output_truncated_in_json": false, "full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt", - "output": "PVE01_RELEVANT_ARCHIVE_FILE_COUNT=7\nPVE01_RELEVANT_ARCHIVE_FILES=[{\"path\":\"[XenForo.Info]_language-Russian-(RU)-XF-2.3.10.zip\",\"bytes\":298309,\"sha256\":\"68e0308b23a30dadd6399032fbef22e09693220a97a602ee6ef8a8c5492bce6b\"},{\"path\":\"[XenForo.Info]_language-Russian-(RU)-XFMG.xml.zip\",\"bytes\":19004,\"sha256\":\"ca07af8f88131aa3217fcf1efeeacd20f6af3d97937bce45e202a013103aa78b\"},{\"path\":\"[XenForo.Info]_language-Russian-(RU)-XFRM-2.3.5.zip\",\"bytes\":13985,\"sha256\":\"ca249fcfc31cd0af5c5a8f1b9bfa7688ae2901eeb7390988d6addc6b5359ea35\"},{\"path\":\"[XenForo.Info]_xenForo 2.3.12 Release Edition By xenForo.Info.zip\",\"bytes\":23715636,\"sha256\":\"fc5eae1d72abf2597465379ebf5e7426da2449d4956e3be33188c0650811dfc2\"},{\"path\":\"[XenForo.Info]_xfes_2.3.11_full.zip\",\"bytes\":71079,\"sha256\":\"61acf9377e90dfdf2254b3f32bf2ff7f0af97eb553cc061c9d133cd66682e98d\"},{\"path\":\"[XenForo.Info]_xfmg_2.3.11_full.zip\",\"bytes\":589096,\"sha256\":\"07062ad308ed0da43b9012a520d0723b52d4c9c9faef02663f4f79eeffa48a52\"},{\"path\":\"[XenForo.Info]_xfrm_2.3.11_full.zip\",\"bytes\":325192,\"sha256\":\"a7ba29ca6179dd0606c9a6e43096cce2e7575444e8d9c44412afb64d5d298c21\"}]\nPRIOR_NEWFI_WORKTREE_EXISTS=true\nPRIOR_NEWFI_OPERATION_REFERENCES=[{\"path\":\"docs/operations/addons-language.md\",\"sha256\":\"8ccbeee79e225d5a18cfcd2b186d76c6357608caed7a55fb6c7d06fd2a230a5c\",\"bytes\":2707,\"key_lines\":[\"# Newfi add-ons and Russian language\",\"## Russian language packs\",\"- Core Russian created `language_id=2`, title `Russian (RU)`, language code `ru-RU` through `XF\\\\Service\\\\Language\\\\ImportService`.\",\"- XFMG and XFRM packs were imported into the same entity with `setOverwriteLanguage()` after their add-ons were installed.\",\"- Accepted phrase counts for language 2: XF `11142`, XFMG `722`, XFRM `464`, total `12328`.\",\"- `defaultLanguageId` was changed through the XenForo Option repository from `1` to `2` only after all three packs passed acceptance.\",\"- English (US), language ID 1, remains installed and user-selectable.\",\"- Staging board remains disabled: `boardActive=0`.\",\"- Board title remains `Newfi Staging`.\",\"- Board URL remains `http://newfi-staging.gram1.ru`.\",\"## Rollback\",\"- Pre-add-on rollback: `/root/newfi-task5-preaddons-20260904T223005Z` on VM211.\",\"- DB backup SHA256: `19e347e3966a9933305acfdd0ce5fb8480b34ab31e23b2ff47f5a46bb9cf7a1b`.\",\"- Public tree backup SHA256: `e6ab5203d3bbfe72089648f3ec36a0c8fae7f7a5292ac7d3893ce8d303f8f29a`.\",\"- Both rollback artifacts are root-owned mode `0600` and passed integrity verification.\"]},{\"path\":\"docs/operations/backup-restore.md\",\"sha256\":\"0d0bb33f688f2a44271eaed49b63560619a2442104db886d9c21ec87758f105f\",\"bytes\":3166,\"key_lines\":[\"# Newfi foundation backup and restore\",\"- Source VM: `211` (`newfi-staging`)\",\"- Canonical sealed state: `/var/lib/homelab-backup/cloud-quorum/vm211/vm211-pve03-20260906T083057Z.json`\",\"- Bounded Cloud-A evidence: `/var/lib/homelab-backup/vm-restore-validation/vm211/vm211-pve03-20260906T083057Z.json`\",\"- Full isolated restore evidence: `/var/lib/homelab-backup/vm-restore-validation/vm211/vm211-pve03-20260906T083057Z-newfi-full.json`\",\"The backup used the current homelab VM cloud-quorum worker/transport contract with a root-only bounded worker copy whose only allowlist extension was VM211 as `pve03/qemu`. The shared worker was not modified.\",\"## Full isolated restore\",\"The same sealed generation was reconstructed from Cloud A and restored with native Proxmox `qmrestore` into temporary VMID `9211`.\",\"- VM9211 was restored stopped.\",\"- Every restored NIC was set to `link_down=1` before boot.\",\"- No application mail path was invoked.\",\"The restored guest proved:\",\"- default XenForo language ID `2`\",\"- language code `ru-RU`\",\"- protected DB/mail configuration permissions\",\"## Restore-attempt RCAs\",\"`NEWFI76` reconstructed the correct bytes and archive SHA but used the temporary basename `archive.vma.zst`. Proxmox `qmrestore` determines archive metadata from the filename and rejected it before restore. Committed-state checks proved no VM9211 residue.\",\"`NEWFI78` then completed a real isolated restore, but its acceptance verifier used a Cyrillic substring test for the language title. XenForo's authoritative restored record was `language_id=2`, `title=Russian (RU)`, `language_code=ru-RU`; therefore that result was a verifier false negative. Cleanup again left no VM9211 residue.\",\"`NEWFI80` uses the authoritative language ID/code contract and records the accepted full restore evidence.\",\"`./scripts/verify-foundation-restore.sh`\",\"The verifier checks strict SEALED state, bounded Cloud-A recovery evidence, accepted full-restore evidence, VM9211/LV absence and performs a fresh remote seal verification.\"]},{\"path\":\"docs/operations/brand-assets.md\",\"sha256\":\"9fc0b97c73be6462143edd7cf30c23fe68cdd97ac9441fe11b81651d947ef6f1\",\"bytes\":1303,\"key_lines\":[\"The user already installed the profile/community icon and the profile banner manually. This checkpoint deliberately does **not** write avatar/profile/banner records or files and does not alter a header logo. Header/theme composition remains for `STYLE199`.\",\"- XenForo favicon style property `publicFaviconUrl` -> `styles/newfi/brand/brand198/newfidom-favicon-32.accef45839db.png`\",\"- XenForo 192x192 PWA style property `publicIconUrl` -> `styles/newfi/brand/brand198/newfidom-pwa-192.db0307c1a668.png`\",\"- XenForo 512x512 PWA style property `publicIconUrlLarge` -> `styles/newfi/brand/brand198/newfidom-pwa-512.39f204179d59.png`\",\"Promotion contract: staging VM211 apply and VM211 loopback/Host HTTP verification, exact staging rollback proof, staging re-apply, Git commit/push, then production VM210 apply and public `https://newfi.ru` desktop/mobile/manifest/static-asset verification. XenForo application state changes use `StyleProperty::updatePropertyValues` via the repository layer; raw SQL mutations are prohibited.\"]},{\"path\":\"docs/operations/mail.md\",\"sha256\":\"b7e9e8f05389fb14f452f813a8000050852bcdb6219ce6a423fed053b4292690\",\"bytes\":3172,\"key_lines\":[\"# Newfi mail operations\",\"The mail-transport portion of Task 6 was accepted on 2026-09-06 for private staging.\",\"This does **not** close Task 6 as a whole. Registration, email-confirmation/anti-spam configuration, the staging security baseline and registration/login/password-reset acceptance remain pending.\",\"- XenForo transport option remains `sendmail`.\",\"- `/usr/sbin/sendmail` resolves to `/usr/bin/msmtp`.\",\"- Debian packages `msmtp` and `msmtp-mta` are installed.\",\"- `/etc/msmtprc` is `root:xfp_newfi` mode `0640`.\",\"- `/etc/msmtprc` retrieves the credential through `passwordeval`; the credential value is not stored in this repository.\",\"- XenForo `contactEmailAddress`: `aleisaev@yandex.ru`, explicitly approved on 2026-09-06.\",\"- The technical/staging administrator email was not changed as part of this mail work.\",\"Exactly one accepted smoke message was sent through the XenForo application mailer:\",\"- Command ID: `NEWFI-260906-MAIL52`.\",\"- Subject: `[NEWFI] mail acceptance NEWFI-260906-MAIL52`.\",\"- XenForo API path: `newMail()` -> `setTo()` -> `setContent()` -> `send(null, false)`.\",\"- The operator separately confirmed that this exact message arrived in the approved Yandex mailbox.\",\"## Rollback evidence\",\"The mail-transport mutation retained rollback evidence under:\",\"`/root/newfi-task6-mail-pre-20260906T065736Z`\",\"- registration and email-confirmation policy;\",\"- `scripts/verify-staging-security.sh`.\",\"Public routing, `boardActive`, bounce/unsubscribe identities, DNS mail policy and unrelated infrastructure remain outside this accepted mail scope.\"]},{\"path\":\"docs/operations/portal-navigation.md\",\"sha256\":\"66e03d84ade36af39cf518a51bdd842f0800ef232c5a9676970ce9c65ce32553\",\"bytes\":1870,\"key_lines\":[\"# Newfi Portal navigation/widgets checkpoint\",\"This checkpoint extends the accepted `Newfi/Portal` staging entrypoint without changing\",\"the closed-staging or public-cutover boundaries.\",\"- Render the already-existing `whats_new_new_posts` widget on the Portal.\",\"- Render the already-existing `xfrm_whats_new_overview_new_resources` widget on the Portal.\",\"and the Portal template only. VM211 applies the source through XenForo's normal rebuild\",\"Before final acceptance, the command proves rollback by restoring the prior Portal template,\",\"Newfi navigation/phrase disappear while the original Portal remains installed. The same\",\"python3 scripts/verify-portal-navigation.py\",\"The verifier chains the accepted content and Portal verifiers, checks the navigation entry,\",\"phrase, existing widget keys, rendered Portal template, zero custom Newfi widget rows,\",\"zero XenForo errors, `boardActive=0`, `indexRoute=portal/`, VM210 absence and the exact\",\"## Rollback\",\"Restore the previous Portal template, remove this add-on's navigation/phrase `_data` files\"]},{\"path\":\"docs/operations/portal.md\",\"sha256\":\"8fa654db0c45d8fbda6b022cc11ad5597dc5543ab98bcee774034d2718cd8708\",\"bytes\":1648,\"key_lines\":[\"# Newfi Portal staging checkpoint\",\"`Newfi/Portal` is the minimal private-staging landing route for the closed MVP.\",\"- add-on id: `Newfi/Portal`\",\"- public route: `portal`\",\"- public template: `newfi_portal`\",\"- staging `indexRoute`: `portal/`\",\"The Portal is intentionally plain. Navigation/widgets and permanent \\u00ab\\u0411\\u043e\\u043b\\u044c\\u0448\\u0430\\u044f \\u0432\\u043e\\u0434\\u0430\\u00bb\",\"Rollback proof before `indexRoute` change:\",\"6. prove no Portal add-on/route/template residue.\",\"## Verification and rollback\",\"Run `python3 scripts/verify-portal-staging.py` from the implementation worktree.\",\"For rollback after this checkpoint, first restore `indexRoute=forums/` through\",\"remove only `src/addons/Newfi/Portal` from VM211 if the source is intentionally withdrawn.\"]},{\"path\":\"docs/operations/style-staging.md\",\"sha256\":\"7cc57486e57574ce25fd09e1cb03ffb4fd28954415834c757f32c0ca74df8d09\",\"bytes\":2142,\"key_lines\":[\"# Newfi staging style checkpoint\",\"This checkpoint creates a dedicated XenForo child style for private staging.\",\"- Title: `Newfi Staging`\",\"- Parent: style `1` (`Default style`)\",\"- Make it the staging `defaultStyleId`\",\"- Keep `indexRoute=portal/`\",\"style is only a safe inheritance container for the later \\u00ab\\u0411\\u043e\\u043b\\u044c\\u0448\\u0430\\u044f \\u0432\\u043e\\u0434\\u0430\\u00bb design checkpoint,\",\"The accepted state therefore requires zero child-style rows in `xf_style_property`,\",\"`xf_style_property_group` and `xf_template`.\",\"Creation uses `XF\\\\Entity\\\\Style::save()`, the same entity used by the Admin style save flow.\",\"`Style::_postSave()` performs XenForo's rebuild/cache handling.\",\"The staging default is changed only through\",\"`XF\\\\Repository\\\\OptionRepository::updateOption('defaultStyleId', ...)`.\",\"Rollback is proven before acceptance with an explicit PHP-process boundary:\",\"1. In PHP process C, restore `defaultStyleId=1` through `OptionRepository`, then end that process.\",\"2. In fresh PHP process D, prove both the DB option and `XF::options()->defaultStyleId` are `1`.\",\"3. Only then delete the child with `XF\\\\Entity\\\\Style::delete()`.\",\"4. Prove style count returns to one and all accepted verifiers pass.\",\"5. In a fresh process, re-create the child style and set its actual new ID as `defaultStyleId`.\",\"6. In another fresh process, prove DB and application options agree on the final style ID and run the style verifier.\",\"This process split is required because `XF\\\\Entity\\\\Style::_preDelete()` checks the current\",\"application process' cached `options()->defaultStyleId`, not a fresh direct read of `xf_option`.\",\"python3 scripts/verify-style-staging.py\"]},{\"path\":\"docs/checkpoints/private-staging-backup-restore.md\",\"sha256\":\"d8692f662ec16017b4f49c60aa3add6a14c8fab822ab0a9d2272eb20fb9c5e37\",\"bytes\":2138,\"key_lines\":[\"# Newfi private staging \\u2014 fresh backup and full restore gate\",\"Fresh backup command: `NEWFI-260906-FINAL181`\",\"Restore-validation command: `NEWFI-260907-FINAL183`\",\"Sealed state: `/var/lib/homelab-backup/cloud-quorum/vm211/vm211-pve03-20260906T213759Z.json`\",\"Full isolated restore evidence: `/var/lib/homelab-backup/vm-restore-validation/vm211/vm211-pve03-20260906T213759Z-newfi-full.json`\",\"Restored system state after boot convergence: `degraded`\",\"Observed failed units in network-isolated restore: `[\\\"systemd-networkd-wait-online.service\\\"]`\",\"- FINAL181 created the fresh VM211 backup and sealed it with Cloud A + Cloud B quorum 2;\",\"- local backup payload was removed after strict seal;\",\"- temporary VM9211 was restored with unique MAC assignment and all restored NICs link-down before boot;\",\"- restored nginx, MariaDB, PHP-FPM, cron and qemu-guest-agent were required active;\",\"- restored system state had to converge to running or degraded;\",\"- restored XenForo application state, add-ons, routes, zero-content invariants, KB, PWA files and protected-file metadata were verified through QGA;\",\"- VM9211, its config, restore LVs and reconstruction work were removed after proof;\",\"- source VM211 remained system-running with zero failed units before and after the restore drill;\",\"This completes the approved **private staging** implementation gate. It does not authorize VM210 creation, production deployment, board enablement, route 998 cutover, or public launch. `SHELL_INCIDENT=OPEN_RCA_UNPROVEN` remains open.\"]},{\"path\":\"scripts/verify-addons-language.sh\",\"sha256\":\"c825959b40cb6713aa7932e290d0e1b104ad2e3173d361bf6de617669f0324f0\",\"bytes\":4599,\"key_lines\":[\"language_rows=$(mariadb --defaults-extra-file=/etc/newfi/db.cnf --batch --skip-column-names -e \\\"SELECT CONCAT_WS(0x7c,language_id,title,language_code,parent_id,user_selectable) FROM xf_language ORDER BY language_id\\\")\",\"phrase_rows=$(mariadb --defaults-extra-file=/etc/newfi/db.cnf --batch --skip-column-names -e \\\"SELECT CONCAT_WS(0x7c,addon_id,COUNT(*)) FROM xf_phrase WHERE language_id=2 GROUP BY addon_id ORDER BY addon_id\\\")\",\"phrases=$(mariadb --defaults-extra-file=/etc/newfi/db.cnf --batch --skip-column-names -e \\\"SELECT COUNT(*) FROM xf_phrase WHERE language_id=2\\\")\",\"expected_languages=$(printf \\\"1|English (US)|en-US|0|1\\\\n2|Russian (RU)|ru-RU|0|1\\\")\",\"printf \\\"ADDON_ROWS_BEGIN\\\\n%s\\\\nADDON_ROWS_END\\\\nLANGUAGE_ROWS_BEGIN\\\\n%s\\\\nLANGUAGE_ROWS_END\\\\nRU_PHRASE_ROWS_BEGIN\\\\n%s\\\\nRU_PHRASE_ROWS_END\\\\nDEFAULT_LANGUAGE_ID=%s\\\\nRU_PHRASE_COUNT=%s\\\\nDB_TABLES=%s\\\\nBOARD_ROW=%s|%s|%s\\\\nERROR_LOG_COUNT=%s\\\\nMANUAL_JOB_COUNT=%s\\\\n\\\" \\\"$addon_rows\\\" \\\"$language_rows\\\" \\\"$phrase_rows\\\" \\\"$default_lang\\\" \\\"$phrases\\\" \\\"$tables\\\" \\\"$board\\\" \\\"$title\\\" \\\"$url\\\" \\\"$errors\\\" \\\"$manual\\\"\",\"test \\\"$language_rows\\\" = \\\"$expected_languages\\\"\",\"test \\\"$title\\\" = \\\"Newfi Staging\\\"\",\"test \\\"$url\\\" = \\\"http://newfi-staging.gram1.ru\\\"\",\"printf \\\"NEWFI_TASK5_VERIFY=PASS\\\\n\\\"\"]},{\"path\":\"scripts/verify-foundation-restore.sh\",\"sha256\":\"cc8b821ffd64c8b2d780eb6efaf96f3724230c2bfe50c7db08c4162f79dc2186\",\"bytes\":5019,\"key_lines\":[\"STATE=/var/lib/homelab-backup/cloud-quorum/vm211/$GEN.json\",\"BOUNDED=/var/lib/homelab-backup/vm-restore-validation/vm211/$GEN.json\",\"FULL=/var/lib/homelab-backup/vm-restore-validation/vm211/${GEN}-newfi-full.json\",\"print(\\\"STOP=RESTORE_EVIDENCE_INVALID:\\\"+path)\",\"\\\"restored_guest_proof\\\",\",\"and bounded.get(\\\"schema\\\")==\\\"homelab-vm-restore-validation-v1\\\"\",\"and full.get(\\\"schema\\\")==\\\"newfi-foundation-full-restore-v1\\\"\",\"and full.get(\\\"full_restore_proven\\\") is True\",\"and guest.get(\\\"default_language_id\\\")==\\\"2\\\"\",\"and guest.get(\\\"default_language_code\\\")==\\\"ru-RU\\\"\",\"print(\\\"NEWFI_FOUNDATION_RESTORE_VERIFY=FAIL\\\")\",\"print(\\\"NEWFI_FOUNDATION_RESTORE_VERIFY=FAIL_TEST_VM_RESIDUE\\\")\",\"print(\\\"NEWFI_FOUNDATION_RESTORE_VERIFY=FAIL_TEST_LV_RESIDUE\\\")\",\"\\\"verify-sealed\\\",\",\"\\\"pve01-mail-01-crypt:homelab-backups\\\",\",\"\\\"pve01-mail-02-crypt:homelab-backups\\\",\",\"\\\"/var/lib/homelab-backup/cloud-quorum\\\"\",\"print(\\\"NEWFI_FOUNDATION_RESTORE_VERIFY=FAIL_REMOTE_SEAL\\\")\",\"print(\\\"NEWFI_FOUNDATION_RESTORE_VERIFY=PASS\\\")\",\"print(\\\"FULL_RESTORE_PROVEN=true\\\")\"]},{\"path\":\"scripts/verify-brand-assets.py\",\"sha256\":\"efaf9bd3af3ec7d28a8ffd3f3ddf88d25f9e76bbd1c5e262e902523716ede6af\",\"bytes\":1165,\"key_lines\":[\"if cfg['header_logo']!='deferred_to_STYLE199_no_manual_asset_overwrite': raise RuntimeError('logo')\",\"print('NEWFI_BRAND_ASSET_SOURCE_VERIFY=PASS')\"]},{\"path\":\"scripts/verify-portal-staging.py\",\"sha256\":\"07cdf461aa7126a9519b209f431c0dbff093b3984f372fa855bb6bf53920fab9\",\"bytes\":5003,\"key_lines\":[\"\\\"src/addons/Newfi/Portal/addon.json\\\",\",\"\\\"src/addons/Newfi/Portal/Pub/Controller/Portal.php\\\",\",\"\\\"src/addons/Newfi/Portal/Pub/View/Portal.php\\\",\",\"\\\"src/addons/Newfi/Portal/_data/routes.xml\\\",\",\"\\\"src/addons/Newfi/Portal/_data/templates.xml\\\",\",\"if b\\\"PASS\\\" not in run([str(ROOT/\\\"scripts/verify-content-structure.sh\\\")],t=120).stdout:\",\"$a=$app->addOnManager()->getById('Newfi/Portal');\",\"$row=$db->fetchRow(\\\"SELECT addon_id,active,is_processing,last_pending_action FROM xf_addon WHERE addon_id='Newfi/Portal'\\\");\",\"'route_rows'=>(int)$db->fetchOne(\\\"SELECT COUNT(*) FROM xf_route WHERE addon_id='Newfi/Portal' AND route_type='public' AND route_prefix='portal'\\\"),\",\"'route_controller'=>(string)$db->fetchOne(\\\"SELECT controller FROM xf_route WHERE addon_id='Newfi/Portal' AND route_type='public' AND route_prefix='portal' LIMIT 1\\\"),\",\"'template_rows'=>(int)$db->fetchOne(\\\"SELECT COUNT(*) FROM xf_template WHERE addon_id='Newfi/Portal' AND type='public' AND title='newfi_portal'\\\"),\",\"'controller_loads'=>class_exists('Newfi\\\\\\\\Portal\\\\\\\\Pub\\\\\\\\Controller\\\\\\\\Portal'),\",\"'view_loads'=>class_exists('Newfi\\\\\\\\Portal\\\\\\\\Pub\\\\\\\\View\\\\\\\\Portal')\",\"and r[\\\"route_rows\\\"]==1 and r[\\\"route_controller\\\"]==\\\"Newfi\\\\\\\\Portal:Portal\\\"\",\"and r[\\\"template_rows\\\"]==1 and r[\\\"index_route\\\"]==\\\"portal/\\\" and r[\\\"board_active\\\"]==\\\"0\\\"\",\"print(\\\"NEWFI_PORTAL_VERIFY=\\\"+json.dumps({\\\"result\\\":\\\"PASS\\\",\\\"runtime\\\":r,\\\"public_parked_exact\\\":True,\\\"vm210_absent\\\":True},sort_keys=True))\"]},{\"path\":\"scripts/verify-style-staging.py\",\"sha256\":\"2a3bc464da8d0dee93e2fd16a8edfd6a7f750a8d28653d5f5bf77691fb86afad\",\"bytes\":4857,\"key_lines\":[\"DECL=ROOT/\\\"config/newfi-style-staging.json\\\"\",\"\\\"title\\\":\\\"Newfi Staging\\\",\",\"\\\"parent_style_id\\\":1,\",\"\\\"description\\\":\\\"Private staging style container; visual identity intentionally not defined.\\\",\",\"[str(ROOT/\\\"scripts/verify-content-structure.sh\\\")],\",\"[\\\"/usr/bin/python3\\\",str(ROOT/\\\"scripts/verify-portal-staging.py\\\")],\",\"[\\\"/usr/bin/python3\\\",str(ROOT/\\\"scripts/verify-portal-navigation.py\\\")]\",\"$styles=$db->fetchAll(\\\"\",\"SELECT style_id,parent_id,title,description,user_selectable,enable_variations,designer_mode\",\"FROM xf_style\",\"WHERE title='Newfi Staging'\",\"ORDER BY style_id\",\"$style=(count($styles)===1 ? $styles[0] : null);\",\"$id=$style ? (int)$style['style_id'] : 0;\",\"'matching_styles'=>$styles,\",\"'style_count'=>(int)$db->fetchOne(\\\"SELECT COUNT(*) FROM xf_style\\\"),\",\"'default_style_id'=>(string)$db->fetchOne(\\\"SELECT option_value FROM xf_option WHERE option_id='defaultStyleId'\\\"),\",\"'default_style_options'=>(string)$app->options()->defaultStyleId,\",\"'property_rows'=>$id ? (int)$db->fetchOne(\\\"SELECT COUNT(*) FROM xf_style_property WHERE style_id=?\\\", $id) : -1,\",\"'property_group_rows'=>$id ? (int)$db->fetchOne(\\\"SELECT COUNT(*) FROM xf_style_property_group WHERE style_id=?\\\", $id) : -1,\",\"'template_rows'=>$id ? (int)$db->fetchOne(\\\"SELECT COUNT(*) FROM xf_template WHERE style_id=?\\\", $id) : -1,\",\"if len(r[\\\"matching_styles\\\"])!=1:\",\"raise RuntimeError(\\\"style-match\\\")\",\"s=r[\\\"matching_styles\\\"][0]\",\"sid=int(s[\\\"style_id\\\"])\"]},{\"path\":\"scripts/verify-web-foundation.sh\",\"sha256\":\"f7ad539ed2b5c3d7f09aaea0e84b82679a608b60d105271bcb62f0443bb2d84b\",\"bytes\":3787,\"key_lines\":[\"NGINX_EXPECTED=$(sha256sum \\\"$ROOT/deploy/nginx/newfi-staging.conf\\\" | awk '{print $1}')\",\"FPM_EXPECTED=$(sha256sum \\\"$ROOT/deploy/php/newfi-staging-pool.conf\\\" | awk '{print $1}')\",\"probe=/var/www/forums/newfi/public/__newfi_verify.txt\",\"trap \\\"rm -f \\\\\\\"$probe\\\\\\\" /run/newfi-web-verify.out\\\" EXIT\",\"printf \\\"NEWFI_WEB_VERIFY=PASS\\\\n\\\" > \\\"$probe\\\"\",\"code=$(curl -sS -H \\\"Host: newfi-staging.gram1.ru\\\" -o /run/newfi-web-verify.out -w \\\"%{http_code}\\\" http://127.0.0.1/__newfi_verify.txt)\",\"grep -qx \\\"NEWFI_WEB_VERIFY=PASS\\\" /run/newfi-web-verify.out\",\"for path in /src/XF.php /internal_data/test.php /install/ /data/test.php /library/test.php; do code=$(curl -sS -o /dev/null -w \\\"%{http_code}\\\" -H \\\"Host: newfi-staging.gram1.ru\\\" \\\"http://127.0.0.1$path\\\"); test \\\"$code\\\" = 403; done\",\"printf 'NEWFI_WEB_FOUNDATION_VERIFY=PASS\\\\n'\"]}]\nPVE01_OPERATION_DOC_MATCHES=[{\"path\":\"/etc/pve/HOMELAB_FULL_HANDOFF_HISTORICAL_2026-07-09.md\",\"sha256\":\"40913559857c212486760d696140e746f7b97fbdde7a226956a5ac3cfe6eb1df\",\"hits\":[\"6. External Homepage link `https://aleisaevn.netcraze.pro:5083/` is classified as an external link, not a homelab-managed service.\",\"PASSWORD|TOKEN|SECRET|PRIVATE|KEY|ROOT_USER|ROOT_PASSWORD|ENCRYPTION_KEY|AUTH|SMTP|MSMTP|COOKIE|SESSION|AGE-SECRET|\\\\.env|[SENSITIVE_PATH]|[SENSITIVE_PATH]|[SENSITIVE_FILE]\",\"STATUS=OK TS=2026-07-09T16:46:31Z TYPE=service-readiness-final BAD=0 SERVICE=paperless HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://paper.gram1.ru STATE=app:running/healthy,postgres:running,redis:running\",\"- Route/Homepage/Kuma OK.\",\"STATUS=OK TS=2026-07-09T16:50:21Z TYPE=service-readiness-final BAD=0 SERVICE=memos HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://memos.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T17:40:57Z TYPE=service-readiness-final BAD=0 SERVICE=linkding HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://linkding.vpn.gram1.ru STATE=running/healthy\",\"STATUS=OK TS=2026-07-09T17:47:41Z TYPE=healthchecks-canonical-domain-repair BAD=0 SERVICE=healthchecks CANONICAL_URL=https://checks.vpn.gram1.ru OLD_ALIAS=https://healthchecks.vpn.gram1.ru OLD_ALIAS_DEFAULT_PAGE=1 HOMEPAGE=OK KUMA=OK BESZEL_NTFY_KUMA=OK LOGS=OK NOTE=service-readiness-count-unchanged\",\"STATUS=OK TS=2026-07-09T17:47:41Z TYPE=service-readiness-final BAD=0 SERVICE=healthchecks HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://checks.vpn.gram1.ru STATE=running/healthy NOTE=canonical-domain-corrected-from-healthchecks-vpn-to-checks-vpn\",\"STATUS=OK TS=2026-07-09T17:55:47Z TYPE=service-readiness-final BAD=0 SERVICE=vikunja HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://vikunja.vpn.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T18:01:02Z TYPE=service-readiness-final BAD=0 SERVICE=bookstack HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://bookstack.vpn.gram1.ru STATE=app:running/nohealth,db:running/nohealth\",\"STATUS=OK TS=2026-07-09T18:13:21Z TYPE=service-readiness-final BAD=0 SERVICE=stirling-pdf HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://pdf.vpn.gram1.ru STATE=running/healthy\",\"STATUS=OK TS=2026-07-09T18:19:10Z TYPE=service-readiness-final BAD=0 SERVICE=jellyfin HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://jellyfin.vpn.gram1.ru STATE=running/healthy\",\"STATUS=OK TS=2026-07-09T18:25:21Z TYPE=service-readiness-final BAD=0 SERVICE=audiobookshelf HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://audiobooks.vpn.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T18:57:16Z TYPE=service-readiness-final BAD=0 SERVICE=calibre-web HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://books.vpn.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T19:07:39Z TYPE=service-readiness-final BAD=0 SERVICE=homeassistant HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://homeassistant.vpn.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T19:23:55Z TYPE=service-readiness-final BAD=0 SERVICE=it-tools HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://it-tools.vpn.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T19:32:34Z TYPE=service-readiness-final BAD=0 SERVICE=karakeep HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://karakeep.vpn.gram1.ru STATE=app:running/healthy,meilisearch:running/nohealth,chrome:running/nohealth\",\"STATUS=OK TS=2026-07-09T19:42:26Z TYPE=service-readiness-final BAD=0 SERVICE=n8n HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://n8n.vpn.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T19:50:17Z TYPE=service-readiness-final BAD=0 SERVICE=node-red HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://node-red.vpn.gram1.ru STATE=running/healthy\",\"STATUS=OK TS=2026-07-09T19:59:09Z TYPE=service-readiness-final BAD=0 SERVICE=syncthing HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://syncthing.vpn.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T20:12:53Z TYPE=service-readiness-final BAD=0 SERVICE=immich HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://photos.gram1.ru STATE=server:running/healthy,postgres:running/healthy,machine-learning:running/healthy,redis:running/healthy\",\"STATUS=OK TS=2026-07-09T20:45:50Z TYPE=service-readiness-final BAD=0 SERVICE=nextcloud HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK URL=https://nc.gram1.ru STATE=vm150:running,nextcloud-status:installed-maintenance-false,turn:monitored\",\"STATUS=OK TS=2026-07-09T20:55:37Z TYPE=service-readiness-final BAD=0 SERVICE=dns1 HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK CONFIG_SYNC=OK BACKUP_SLA=OK ALERTING=OK URL=https://dns1.vpn.gram1.ru STATE=adguard-ui:monitored,dns-tcp:monitored,unbound:monitored\",\"- Homepage card OK.\",\"STATUS=OK TS=2026-07-09T20:55:37Z TYPE=service-readiness-final BAD=0 SERVICE=dns2 HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK CONFIG_SYNC=OK BACKUP_SLA=OK ALERTING=OK URL=https://dns2.vpn.gram1.ru STATE=adguard-ui:monitored,dns-tcp:monitored,unbound:monitored\",\"- Homepage card OK.\",\"## 47. homepage\",\"STATUS=OK TS=2026-07-09T20:55:37Z TYPE=service-readiness-final BAD=0 SERVICE=homepage HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK URL=https://home.gram1.ru STATE=container:running/healthy,config:backed-by-dockge-stacks\",\"- Homepage container `running/healthy`.\",\"- Kuma monitor ID 16 `Homepage HTTPS` green.\"]},{\"path\":\"/etc/pve/HOMEPAGE_BACKUP_COVERAGE_MATRIX.md\",\"sha256\":\"b0c75b5656063afdfd7db57ffd3450098b27e75335eab78c9239bda2815887ae\",\"hits\":[\"# HOMEPAGE_BACKUP_COVERAGE_MATRIX\",\"Scope: active Homepage cards with non-empty href only.\",\"| Homepage | https://home.gram1.ru | 190 | 4 | 96 | EVIDENCE_FOUND_REVIEW |\"]},{\"path\":\"/etc/pve/31_HOMELAB_REFERENCE.md\",\"sha256\":\"5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66\",\"hits\":[\"- Homepage/Prometheus retired references absent; Uptime Kuma orphan extra_hosts removed.\",\"HEALTH_NOT_OK item=homepage-service-catalog-slo.txt line=STATUS=WARN\",\"- homepage.vpn.gram1.ru -> http://127.0.0.1:3000, cert=32.\",\"- homepage.\",\"- Admin/dashboard: homepage, dockge, netbox, dozzle, NPMplus VPN admin.\",\"- Homepage: 127.0.0.1:3000.\",\"- Other observed WARN backlog files include container-image-lifecycle-slo, cron-job-monitoring-slo, direct-heartbeat-pilot-readiness, healthchecks-heartbeat-coverage, healthchecks-job-coverage, healthchecks-job-monitoring-slo, homepage-service-catalog-slo, ingress-dns-route-slo, observability-health-surface-slo and security-vulnerability-slo.\",\"| home.gram1.ru | http://127.0.0.1:3000 | edge-vm / homepage | homepage container, dashboard route |\",\"| homepage.vpn.gram1.ru | http://127.0.0.1:3000 | homepage |\",\"- Discovery proof records DNS, HTTPS/TLS headers, reverse-proxy candidates, compose files, domain references and homepage config candidates without printing secrets.\",\"- Home portal gap analysis was collected for gethomepage/homepage behind npmplus.\",\"- Proof records Homepage config hashes, redacted current cards/bookmarks, current URLs, npmplus route lines, local web-port probes and known service container candidates.\",\"- Home portal card/API-error analysis was collected before editing Homepage.\",\"- Proof records current card URLs/titles, redacted widget config, redacted Homepage log errors, NPMPlus internal route files/routes and candidate public/VPN cards.\",\"- Homepage services.yaml was backed up, duplicate VPN cards were removed where a non-VPN card existed, and missing web cards for NetBird, Mail and Webmail were added without VPN suffix in the card names.\",\"- Homepage container was restarted and portal/card URLs were checked.\",\"- Corrected Homepage apply removed duplicate VPN cards where a non-VPN card existed and added NetBird, Mail and Webmail cards with non-VPN names.\",\"- Proof checks portal HTTP status, Homepage container state, required cards, duplicate VPN card pairs, current card URLs, redacted API-error logs and widget configuration.\",\"- Homepage API error root-cause analysis was collected after the UI showed API errors.\",\"- Current evidence points to the Open-Meteo/weather widget timing out from Homepage, separate from service cards.\",\"- HTTP 200 for the portal is not sufficient for UI closure when Homepage logs still contain API errors.\",\"- Open-Meteo/weather widget was disabled after root-cause analysis showed Homepage API errors from api.open-meteo.com timeouts.\",\"- Portal closure now requires current Homepage API-error logs to be zero after restart/reload.\",\"- Audit extracts current Homepage href URLs and checks whether each opens with an acceptable HTTP status.\",\"- Explicit VPN duplicate cards were removed from Homepage with a short transparent perl edit: Homepage VPN, Authentik VPN, Gitea VPN and Uptime Kuma VPN.\",\"- Remaining Homepage duplicate/VPN/router occurrences were inspected after corrected cleanup still reported REVIEW.\",\"- Homepage duplicate cleanup was rechecked against active config files only, excluding logs and backup files.\",\"- Active Homepage services/bookmarks files were cleaned from semantic VPN duplicate cards and old router URL references.\",\"- Removed targets: Homepage VPN, Authentik VPN, Gitea VPN and Uptime Kuma VPN, plus matching vpn.gram1.ru duplicate URLs.\",\"- Analysis checks URL body fingerprints, NPMPlus route config matches, service container candidates and Homepage card lines.\"]},{\"path\":\"/etc/pve/HOMELAB_FULL_HANDOFF_CURRENT.md\",\"sha256\":\"82a6060ccc216849c55790a3489ef157d5551a0c7cef0c5ec9abd35f569c7940\",\"hits\":[\"3. Add a read-only observer status card to Homepage or cluster-admin webpanel.\",\"6. External Homepage link `https://aleisaevn.netcraze.pro:5083/` is classified as an external link, not a homelab-managed service.\",\"PASSWORD|TOKEN|SECRET|PRIVATE|KEY|ROOT_USER|ROOT_PASSWORD|ENCRYPTION_KEY|AUTH|SMTP|MSMTP|COOKIE|SESSION|AGE-SECRET|\\\\.env|[SENSITIVE_PATH]|[SENSITIVE_PATH]|[SENSITIVE_FILE]\",\"STATUS=OK TS=2026-07-09T16:46:31Z TYPE=service-readiness-final BAD=0 SERVICE=paperless HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://paper.gram1.ru STATE=app:running/healthy,postgres:running,redis:running\",\"- Route/Homepage/Kuma OK.\",\"STATUS=OK TS=2026-07-09T16:50:21Z TYPE=service-readiness-final BAD=0 SERVICE=memos HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://memos.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T17:40:57Z TYPE=service-readiness-final BAD=0 SERVICE=linkding HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://linkding.vpn.gram1.ru STATE=running/healthy\",\"STATUS=OK TS=2026-07-09T17:47:41Z TYPE=healthchecks-canonical-domain-repair BAD=0 SERVICE=healthchecks CANONICAL_URL=https://checks.vpn.gram1.ru OLD_ALIAS=https://healthchecks.vpn.gram1.ru OLD_ALIAS_DEFAULT_PAGE=1 HOMEPAGE=OK KUMA=OK BESZEL_NTFY_KUMA=OK LOGS=OK NOTE=service-readiness-count-unchanged\",\"STATUS=OK TS=2026-07-09T17:47:41Z TYPE=service-readiness-final BAD=0 SERVICE=healthchecks HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://checks.vpn.gram1.ru STATE=running/healthy NOTE=canonical-domain-corrected-from-healthchecks-vpn-to-checks-vpn\",\"STATUS=OK TS=2026-07-09T17:55:47Z TYPE=service-readiness-final BAD=0 SERVICE=vikunja HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://vikunja.vpn.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T18:01:02Z TYPE=service-readiness-final BAD=0 SERVICE=bookstack HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://bookstack.vpn.gram1.ru STATE=app:running/nohealth,db:running/nohealth\",\"STATUS=OK TS=2026-07-09T18:13:21Z TYPE=service-readiness-final BAD=0 SERVICE=stirling-pdf HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://pdf.vpn.gram1.ru STATE=running/healthy\",\"STATUS=OK TS=2026-07-09T18:19:10Z TYPE=service-readiness-final BAD=0 SERVICE=jellyfin HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://jellyfin.vpn.gram1.ru STATE=running/healthy\",\"STATUS=OK TS=2026-07-09T18:25:21Z TYPE=service-readiness-final BAD=0 SERVICE=audiobookshelf HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://audiobooks.vpn.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T18:57:16Z TYPE=service-readiness-final BAD=0 SERVICE=calibre-web HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://books.vpn.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T19:07:39Z TYPE=service-readiness-final BAD=0 SERVICE=homeassistant HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://homeassistant.vpn.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T19:23:55Z TYPE=service-readiness-final BAD=0 SERVICE=it-tools HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://it-tools.vpn.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T19:32:34Z TYPE=service-readiness-final BAD=0 SERVICE=karakeep HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://karakeep.vpn.gram1.ru STATE=app:running/healthy,meilisearch:running/nohealth,chrome:running/nohealth\",\"STATUS=OK TS=2026-07-09T19:42:26Z TYPE=service-readiness-final BAD=0 SERVICE=n8n HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://n8n.vpn.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T19:50:17Z TYPE=service-readiness-final BAD=0 SERVICE=node-red HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://node-red.vpn.gram1.ru STATE=running/healthy\",\"STATUS=OK TS=2026-07-09T19:59:09Z TYPE=service-readiness-final BAD=0 SERVICE=syncthing HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://syncthing.vpn.gram1.ru STATE=running/nohealth\",\"STATUS=OK TS=2026-07-09T20:12:53Z TYPE=service-readiness-final BAD=0 SERVICE=immich HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://photos.gram1.ru STATE=server:running/healthy,postgres:running/healthy,machine-learning:running/healthy,redis:running/healthy\",\"STATUS=OK TS=2026-07-09T20:45:50Z TYPE=service-readiness-final BAD=0 SERVICE=nextcloud HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK URL=https://nc.gram1.ru STATE=vm150:running,nextcloud-status:installed-maintenance-false,turn:monitored\",\"STATUS=OK TS=2026-07-09T20:55:37Z TYPE=service-readiness-final BAD=0 SERVICE=dns1 HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK CONFIG_SYNC=OK BACKUP_SLA=OK ALERTING=OK URL=https://dns1.vpn.gram1.ru STATE=adguard-ui:monitored,dns-tcp:monitored,unbound:monitored\",\"- Homepage card OK.\",\"STATUS=OK TS=2026-07-09T20:55:37Z TYPE=service-readiness-final BAD=0 SERVICE=dns2 HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK CONFIG_SYNC=OK BACKUP_SLA=OK ALERTING=OK URL=https://dns2.vpn.gram1.ru STATE=adguard-ui:monitored,dns-tcp:monitored,unbound:monitored\",\"- Homepage card OK.\",\"## 47. homepage\",\"STATUS=OK TS=2026-07-09T20:55:37Z TYPE=service-readiness-final BAD=0 SERVICE=homepage HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK URL=https://home.gram1.ru STATE=container:running/healthy,config:backed-by-dockge-stacks\",\"- Homepage container `running/healthy`.\"]},{\"path\":\"/etc/pve/HOMELAB_CLUSTER_BACKLOG.md\",\"sha256\":\"9bcf7d68af10738179b923e6d870e692b4404db55b3ceccc2170ba4f525baf1f\",\"hits\":[\"- Finish Homepage final validation: YAML, siteMonitor, links, no API errors.\",\"- Build Homepage link validator: HTTP status + not NPMPlus default page.\",\"- Maintain backup coverage matrix for all Homepage services.\",\"- Add/verify restore dry-runs for Vaultwarden, Gitea, Grafana, Alertmanager, NPMplus, Homepage, NetBox, Paperless, Memos, Nextcloud, Immich, Jellyfin, BookStack, Vikunja, SearXNG, AdGuard DNS1/DNS2 and other Homepage services.\",\"- Back up NPMPlus config, certificates and Homepage config.\",\"- Create disaster recovery runbooks for edge-vm, pve01, router config, NPMPlus/Homepage and Nextcloud VM.\",\"- Add blackbox-style checks for Homepage cards.\",\"- Build one dashboard for backup, restore, Homepage, Prometheus, Alertmanager, cloud quota and timers.\",\"## P2 Homepage UX\",\"- Apply siteMonitor policy carefully; Router/Homepage/NPMplus/Public Domain are special cases.\",\"1. Finish Homepage final validation.\",\"3. Build backup coverage matrix for all Homepage services.\",\"5. Add Homepage blackbox checks.\"]},{\"path\":\"/etc/pve/HOMEPAGE_BACKUP_GAP_CLASSIFICATION.md\",\"sha256\":\"7536d78738a7ab30e45b6a8f42cf4b32b79793b321ae0825158da999d6a2adda\",\"hits\":[\"# HOMEPAGE_BACKUP_GAP_CLASSIFICATION\",\"Goal: every Homepage card must be classified and either covered, explicitly stateless/config-only, or closed with backup+restore+health evidence.\",\"- OPEN becomes CLOSED only when evidence file/proof exists and HOMEPAGE_BACKUP_COVERAGE_MATRIX.md is updated.\",\"- Existing backup coverage must be mapped by exact service name/path, not guessed from fuzzy grep counts.\"]},{\"path\":\"/etc/pve/HOMELAB_ASSISTANT_ERROR_REGISTER.md\",\"sha256\":\"3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0\",\"hits\":[\"- Rule: home portal closure requires current Homepage API-error logs to be zero after restart/reload, not only HTTP 200.\",\"- If Homepage UI shows API error or logs contain current httpProxy/API timeout errors, the portal is REVIEW until the widget/API cause is disabled or fixed.\",\"- Rule: Homepage cleanup validation must check active config files only, not logs or backup files.\",\"- Active files are services.yaml, bookmarks.yaml, widgets.yaml, settings.yaml and docker.yaml under /opt/stacks/homepage/config.\",\"- Rule: Homepage link validation must not treat HTTP 200 as success if the body is the NPMPlus default \\u201cCongratulations\\u201d / host-not-set-up page.\",\"- Context: attempted Netcraze router ACL apply through SSH stdin/multiline for Homepage Moscow Router monitor fix.\",\"- Context: proof 400 tested Moscow router HTTPS monitor from Homepage container with custom Node lookup callback.\",\"- Context: Moscow Router Homepage monitor after ACL fix.\",\"- Impact: Homepage siteMonitor cannot be made green via direct router HTTP URL until router web service allows the Bridge1/Proxmox/protected segment or an explicit safe monitor endpoint is used.\",\"- Context: Moscow Router Homepage siteMonitor attempt using http://:5080.\",\"- Evidence: proof 405 showed route to via Docker bridge and Homepage container ECONNRESET.\",\"- Impact: do not use directly as Homepage siteMonitor from edge-vm.\",\"- Mitigation: use dedicated edge-vm health endpoint that checks router TCP :5080 and returns HTTP 200/503 for Homepage.\",\"## HOMEPAGE_ROUTER_MOSCOW_YAML_TITLE_SHAPE_MISMATCH_20260701\",\"- Context: applying Moscow Router Homepage siteMonitor health endpoint.\",\"- Mistake: assistant apply script matched only property-style cards with `title`, but active Homepage YAML can use service-name-key style like `- Service Name:`.\",\"## HOMEPAGE_ROUTER_MOSCOW_APPLY_SCRIPT_SYNTAX_ERROR_20260701\",\"- Context: applying Moscow Router Homepage health endpoint.\",\"- Evidence: proof 408 showed SyntaxError in /tmp/homepage-router-moscow-apply-fixed.py.\",\"- Actual impact: YAML was not changed, so Homepage green dot could not appear.\",\"## MSMTP_SECRET_SOURCE_PARSE_ERROR_576_20260701\",\"- Context: proof 576 installed msmtp but sendmail auth test failed.\",\"- Issue: [SENSITIVE_PATH] was sourced as shell, but SMTP password contained shell-special characters; source failed and auth used an invalid/truncated secret path.\",\"- Impact: msmtp package installed, but mail sending was not proven working.\",\"- Rule: never source SMTP secret files containing arbitrary passwords; store password base64 and use msmtp passwordeval helper accessible to www-data.\",\"## FORUM_MSMTP_MAIL_TRANSPORT_STILL_FAILING_20260701\",\"- Context: attempted to fix msmtp config with passwordeval helper.\",\"- Context: SMTP password was exposed in terminal output during failed msmtp setup.\",\"- Context: forum-prod SMTP/msmtp test used invalid or compromised credentials and triggered Mailcow netfilter warnings/ban for 95.84.154.183.\",\"- Action: remove forum-prod msmtp secret/config files so XenForo cannot keep retrying broken SMTP auth.\"]},{\"path\":\"/root/HOMELAB_ASSISTANT_ERROR_REGISTER.md\",\"sha256\":\"ad60bb9478432540af04df8616e7526967c0dc88d79373c041ba0a27c99e271d\",\"hits\":[\"- Rule: home portal closure requires current Homepage API-error logs to be zero after restart/reload, not only HTTP 200.\",\"- If Homepage UI shows API error or logs contain current httpProxy/API timeout errors, the portal is REVIEW until the widget/API cause is disabled or fixed.\",\"- Rule: Homepage cleanup validation must check active config files only, not logs or backup files.\",\"- Active files are services.yaml, bookmarks.yaml, widgets.yaml, settings.yaml and docker.yaml under /opt/stacks/homepage/config.\",\"- Rule: Homepage link validation must not treat HTTP 200 as success if the body is the NPMPlus default \\u201cCongratulations\\u201d / host-not-set-up page.\",\"- Context: attempted Netcraze router ACL apply through SSH stdin/multiline for Homepage Moscow Router monitor fix.\",\"- Context: proof 400 tested Moscow router HTTPS monitor from Homepage container with custom Node lookup callback.\",\"- Context: Moscow Router Homepage monitor after ACL fix.\",\"- Impact: Homepage siteMonitor cannot be made green via direct router HTTP URL until router web service allows the Bridge1/Proxmox/protected segment or an explicit safe monitor endpoint is used.\",\"- Context: Moscow Router Homepage siteMonitor attempt using http://:5080.\",\"- Evidence: proof 405 showed route to via Docker bridge and Homepage container ECONNRESET.\",\"- Impact: do not use directly as Homepage siteMonitor from edge-vm.\",\"- Mitigation: use dedicated edge-vm health endpoint that checks router TCP :5080 and returns HTTP 200/503 for Homepage.\",\"## HOMEPAGE_ROUTER_MOSCOW_YAML_TITLE_SHAPE_MISMATCH_20260701\",\"- Context: applying Moscow Router Homepage siteMonitor health endpoint.\",\"- Mistake: assistant apply script matched only property-style cards with `title`, but active Homepage YAML can use service-name-key style like `- Service Name:`.\",\"## HOMEPAGE_ROUTER_MOSCOW_APPLY_SCRIPT_SYNTAX_ERROR_20260701\",\"- Context: applying Moscow Router Homepage health endpoint.\",\"- Evidence: proof 408 showed SyntaxError in /tmp/homepage-router-moscow-apply-fixed.py.\",\"- Actual impact: YAML was not changed, so Homepage green dot could not appear.\",\"## MSMTP_SECRET_SOURCE_PARSE_ERROR_576_20260701\",\"- Context: proof 576 installed msmtp but sendmail auth test failed.\",\"- Issue: [SENSITIVE_PATH] was sourced as shell, but SMTP password contained shell-special characters; source failed and auth used an invalid/truncated secret path.\",\"- Impact: msmtp package installed, but mail sending was not proven working.\",\"- Rule: never source SMTP secret files containing arbitrary passwords; store password base64 and use msmtp passwordeval helper accessible to www-data.\",\"## FORUM_MSMTP_MAIL_TRANSPORT_STILL_FAILING_20260701\",\"- Context: attempted to fix msmtp config with passwordeval helper.\",\"- Context: SMTP password was exposed in terminal output during failed msmtp setup.\",\"- Context: forum-prod SMTP/msmtp test used invalid or compromised credentials and triggered Mailcow netfilter warnings/ban for 95.84.154.183.\",\"- Action: remove forum-prod msmtp secret/config files so XenForo cannot keep retrying broken SMTP auth.\"]},{\"path\":\"/root/31_HOMELAB_REFERENCE.before-cr0079-20260817T052826Z.md\",\"sha256\":\"79d217c07b34ccf6e2e30742ddf675afd7321eb4c6fde4086d5092688d96b424\",\"hits\":[\"HEALTH_NOT_OK item=homepage-service-catalog-slo.txt line=STATUS=WARN\",\"- homepage.vpn.gram1.ru -> http://127.0.0.1:3000, cert=32.\",\"- homepage.\",\"- Admin/dashboard: homepage, dockge, netbox, dozzle, NPMplus VPN admin.\",\"- Homepage: 127.0.0.1:3000.\",\"- Other observed WARN backlog files include container-image-lifecycle-slo, cron-job-monitoring-slo, direct-heartbeat-pilot-readiness, healthchecks-heartbeat-coverage, healthchecks-job-coverage, healthchecks-job-monitoring-slo, homepage-service-catalog-slo, ingress-dns-route-slo, observability-health-surface-slo and security-vulnerability-slo.\",\"| home.gram1.ru | http://127.0.0.1:3000 | edge-vm / homepage | homepage container, dashboard route |\",\"| homepage.vpn.gram1.ru | http://127.0.0.1:3000 | homepage |\",\"- Discovery proof records DNS, HTTPS/TLS headers, reverse-proxy candidates, compose files, domain references and homepage config candidates without printing secrets.\",\"- Home portal gap analysis was collected for gethomepage/homepage behind npmplus.\",\"- Proof records Homepage config hashes, redacted current cards/bookmarks, current URLs, npmplus route lines, local web-port probes and known service container candidates.\",\"- Home portal card/API-error analysis was collected before editing Homepage.\",\"- Proof records current card URLs/titles, redacted widget config, redacted Homepage log errors, NPMPlus internal route files/routes and candidate public/VPN cards.\",\"- Homepage services.yaml was backed up, duplicate VPN cards were removed where a non-VPN card existed, and missing web cards for NetBird, Mail and Webmail were added without VPN suffix in the card names.\",\"- Homepage container was restarted and portal/card URLs were checked.\",\"- Corrected Homepage apply removed duplicate VPN cards where a non-VPN card existed and added NetBird, Mail and Webmail cards with non-VPN names.\",\"- Proof checks portal HTTP status, Homepage container state, required cards, duplicate VPN card pairs, current card URLs, redacted API-error logs and widget configuration.\",\"- Homepage API error root-cause analysis was collected after the UI showed API errors.\",\"- Current evidence points to the Open-Meteo/weather widget timing out from Homepage, separate from service cards.\",\"- HTTP 200 for the portal is not sufficient for UI closure when Homepage logs still contain API errors.\",\"- Open-Meteo/weather widget was disabled after root-cause analysis showed Homepage API errors from api.open-meteo.com timeouts.\",\"- Portal closure now requires current Homepage API-error logs to be zero after restart/reload.\",\"- Audit extracts current Homepage href URLs and checks whether each opens with an acceptable HTTP status.\",\"- Explicit VPN duplicate cards were removed from Homepage with a short transparent perl edit: Homepage VPN, Authentik VPN, Gitea VPN and Uptime Kuma VPN.\",\"- Remaining Homepage duplicate/VPN/router occurrences were inspected after corrected cleanup still reported REVIEW.\",\"- Homepage duplicate cleanup was rechecked against active config files only, excluding logs and backup files.\",\"- Active Homepage services/bookmarks files were cleaned from semantic VPN duplicate cards and old router URL references.\",\"- Removed targets: Homepage VPN, Authentik VPN, Gitea VPN and Uptime Kuma VPN, plus matching vpn.gram1.ru duplicate URLs.\",\"- Analysis checks URL body fingerprints, NPMPlus route config matches, service container candidates and Homepage card lines.\",\"- Active Homepage URL: https://home.gram1.ru.\"]},{\"path\":\"/root/31_HOMELAB_REFERENCE.before-cr0080-cutover-20260817T080345Z.md\",\"sha256\":\"87f3e9b362524c9f3ff61b0afe26332f71b5f5f6a1c39bb3a1d31d567c4e8aa5\",\"hits\":[\"HEALTH_NOT_OK item=homepage-service-catalog-slo.txt line=STATUS=WARN\",\"- homepage.vpn.gram1.ru -> http://127.0.0.1:3000, cert=32.\",\"- homepage.\",\"- Admin/dashboard: homepage, dockge, netbox, dozzle, NPMplus VPN admin.\",\"- Homepage: 127.0.0.1:3000.\",\"- Other observed WARN backlog files include container-image-lifecycle-slo, cron-job-monitoring-slo, direct-heartbeat-pilot-readiness, healthchecks-heartbeat-coverage, healthchecks-job-coverage, healthchecks-job-monitoring-slo, homepage-service-catalog-slo, ingress-dns-route-slo, observability-health-surface-slo and security-vulnerability-slo.\",\"| home.gram1.ru | http://127.0.0.1:3000 | edge-vm / homepage | homepage container, dashboard route |\",\"| homepage.vpn.gram1.ru | http://127.0.0.1:3000 | homepage |\",\"- Discovery proof records DNS, HTTPS/TLS headers, reverse-proxy candidates, compose files, domain references and homepage config candidates without printing secrets.\",\"- Home portal gap analysis was collected for gethomepage/homepage behind npmplus.\",\"- Proof records Homepage config hashes, redacted current cards/bookmarks, current URLs, npmplus route lines, local web-port probes and known service container candidates.\",\"- Home portal card/API-error analysis was collected before editing Homepage.\",\"- Proof records current card URLs/titles, redacted widget config, redacted Homepage log errors, NPMPlus internal route files/routes and candidate public/VPN cards.\",\"- Homepage services.yaml was backed up, duplicate VPN cards were removed where a non-VPN card existed, and missing web cards for NetBird, Mail and Webmail were added without VPN suffix in the card names.\",\"- Homepage container was restarted and portal/card URLs were checked.\",\"- Corrected Homepage apply removed duplicate VPN cards where a non-VPN card existed and added NetBird, Mail and Webmail cards with non-VPN names.\",\"- Proof checks portal HTTP status, Homepage container state, required cards, duplicate VPN card pairs, current card URLs, redacted API-error logs and widget configuration.\",\"- Homepage API error root-cause analysis was collected after the UI showed API errors.\",\"- Current evidence points to the Open-Meteo/weather widget timing out from Homepage, separate from service cards.\",\"- HTTP 200 for the portal is not sufficient for UI closure when Homepage logs still contain API errors.\",\"- Open-Meteo/weather widget was disabled after root-cause analysis showed Homepage API errors from api.open-meteo.com timeouts.\",\"- Portal closure now requires current Homepage API-error logs to be zero after restart/reload.\",\"- Audit extracts current Homepage href URLs and checks whether each opens with an acceptable HTTP status.\",\"- Explicit VPN duplicate cards were removed from Homepage with a short transparent perl edit: Homepage VPN, Authentik VPN, Gitea VPN and Uptime Kuma VPN.\",\"- Remaining Homepage duplicate/VPN/router occurrences were inspected after corrected cleanup still reported REVIEW.\",\"- Homepage duplicate cleanup was rechecked against active config files only, excluding logs and backup files.\",\"- Active Homepage services/bookmarks files were cleaned from semantic VPN duplicate cards and old router URL references.\",\"- Removed targets: Homepage VPN, Authentik VPN, Gitea VPN and Uptime Kuma VPN, plus matching vpn.gram1.ru duplicate URLs.\",\"- Analysis checks URL body fingerprints, NPMPlus route config matches, service container candidates and Homepage card lines.\",\"- Active Homepage URL: https://home.gram1.ru.\"]},{\"path\":\"/root/31_HOMELAB_REFERENCE.md\",\"sha256\":\"30dd35bca4094a82dda70b82f0e1714accbf688479ea320bd311d6de63dd4622\",\"hits\":[\"HEALTH_NOT_OK item=homepage-service-catalog-slo.txt line=STATUS=WARN\",\"- homepage.vpn.gram1.ru -> http://127.0.0.1:3000, cert=32.\",\"- homepage.\",\"- Admin/dashboard: homepage, dockge, netbox, dozzle, NPMplus VPN admin.\",\"- Homepage: 127.0.0.1:3000.\",\"- Other observed WARN backlog files include container-image-lifecycle-slo, cron-job-monitoring-slo, direct-heartbeat-pilot-readiness, healthchecks-heartbeat-coverage, healthchecks-job-coverage, healthchecks-job-monitoring-slo, homepage-service-catalog-slo, ingress-dns-route-slo, observability-health-surface-slo and security-vulnerability-slo.\",\"| home.gram1.ru | http://127.0.0.1:3000 | edge-vm / homepage | homepage container, dashboard route |\",\"| homepage.vpn.gram1.ru | http://127.0.0.1:3000 | homepage |\",\"- Discovery proof records DNS, HTTPS/TLS headers, reverse-proxy candidates, compose files, domain references and homepage config candidates without printing secrets.\",\"- Home portal gap analysis was collected for gethomepage/homepage behind npmplus.\",\"- Proof records Homepage config hashes, redacted current cards/bookmarks, current URLs, npmplus route lines, local web-port probes and known service container candidates.\",\"- Home portal card/API-error analysis was collected before editing Homepage.\",\"- Proof records current card URLs/titles, redacted widget config, redacted Homepage log errors, NPMPlus internal route files/routes and candidate public/VPN cards.\",\"- Homepage services.yaml was backed up, duplicate VPN cards were removed where a non-VPN card existed, and missing web cards for NetBird, Mail and Webmail were added without VPN suffix in the card names.\",\"- Homepage container was restarted and portal/card URLs were checked.\",\"- Corrected Homepage apply removed duplicate VPN cards where a non-VPN card existed and added NetBird, Mail and Webmail cards with non-VPN names.\",\"- Proof checks portal HTTP status, Homepage container state, required cards, duplicate VPN card pairs, current card URLs, redacted API-error logs and widget configuration.\",\"- Homepage API error root-cause analysis was collected after the UI showed API errors.\",\"- Current evidence points to the Open-Meteo/weather widget timing out from Homepage, separate from service cards.\",\"- HTTP 200 for the portal is not sufficient for UI closure when Homepage logs still contain API errors.\"\nRELATED_CLUSTER_RESOURCES=[{\"vmid\":160,\"node\":\"pve02\",\"status\":\"running\",\"name_sha256\":\"6c602e84ee97babcf326574bff0e2841d9cacf16d14205d22333adf20ccc31d4\"},{\"vmid\":210,\"node\":\"pve01\",\"status\":\"running\",\"name_sha256\":\"61da6e04392026041610b476d6b0f1772cc199a94154dadc9dea8150655eced0\"},{\"vmid\":211,\"node\":\"pve03\",\"status\":\"running\",\"name_sha256\":\"b2c494a42ab7082a3d4f8184465b9bb4d43c58a397c70e048c49a548c3af139a\"}]\nCLUSTER_BACKUP_JOB_COUNT=0\nCLUSTER_BACKUP_JOBS_SANITIZED=[]\nGUEST_QGA_TRANSPORT_RC=0\nGUEST_EXITCODE=0\nTRANSPORT_STDERR_SHA256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\nGUEST_CONTINUATION_OUTPUT_BEGIN\nXF_SHA=d0c10d91d743e0a541d9a1b201080491dae0a8b1757866f113ef707b83403219\nSERVER_PHP_LINT_RC=0\nSERVER_PHP_LINT_STDERR_SHA256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\nPHP_AUDIT_RC=0\nPHP_AUDIT_STDERR_SHA256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\nPHP_AUDIT_STDERR_BYTES=0\nPHP_AUDIT_OUTPUT_BEGIN\nADDON_COUNT=1\nADDONS=[{\"addon_id\":\"XF\",\"title\":\"XenForo\",\"version_string\":\"2.3.12\",\"active\":1}]\nSUPPORT_ADDON_MATCHES=[]\nXF_ROUTE_COLUMNS=[\"route_id\",\"route_type\",\"route_prefix\",\"sub_name\",\"format\",\"build_class\",\"build_method\",\"controller\",\"context\",\"action_prefix\",\"addon_id\"]\nSUPPORT_ROUTES=[]\nEMAIL_TRANSPORT_TYPE=array\nEMAIL_TRANSPORT_CLASS=\nEMAIL_TRANSPORT_OPTION_KEYS=[\"emailTransport\"]\nDEFAULT_EMAIL_NONEMPTY=true\nCONTACT_EMAIL_NONEMPTY=true\nOPTION_boardUrl_PRESENT=true\nOPTION_boardUrl_NONEMPTY=true\nOPTION_defaultLanguageId_PRESENT=true\nOPTION_defaultLanguageId_NONEMPTY=true\nOPTION_defaultLanguageId_VALUE=1\nOPTION_defaultStyleId_PRESENT=true\nOPTION_defaultStyleId_NONEMPTY=true\nOPTION_defaultStyleId_VALUE=1\nOPTION_friendlyUrls_PRESENT=false\nOPTION_friendlyUrls_NONEMPTY=false\nOPTION_indexRoute_PRESENT=true\nOPTION_indexRoute_NONEMPTY=true\nOPTION_indexRoute_VALUE=forums/\nXF_ERROR_COUNT=16\nMANUAL_JOB_COUNT=0\nPERMISSION_REBUILD_JOB_COUNT=0\nREGISTRATION_ENABLED=false\nNO_MUTATION=true\nPHP_AUDIT_OUTPUT_END\nEXEC_a2698bd30ec6_EXISTS=false\nEXEC_e68e10a6e0ef_EXISTS=false\nEXEC_620e1c7c6b42_EXISTS=false\nMSMTPRC_EXISTS=false\nROOTFILE_76c10b8a6163_EXISTS=false\nROOTFILE_72b7466a08b5_EXISTS=false\nROOTFILE_cc3c8901c551_EXISTS=false\nNO_MUTATION=true\nGUEST_CONTINUATION_OUTPUT_END\nPUBLIC_CONTINUATION_SURFACE={\"SUPPORT_STAFF\":\"404|text/html; charset=utf-8|23063\",\"FAVICON\":\"404|unknown/unknown; charset=utf-8|0\",\"ROBOTS\":\"404|unknown/unknown; charset=utf-8|0\",\"SITEMAP\":\"404|text/plain; charset=utf-8|10\"}\nBASELINE_CONTINUATION_CLEAN=true\nRCA_719_SQL_FIELD_CAUSE=xf_addon uses addon_id; 719 queried add_on_id\nTASK_COMPLETE=true\nTASK_RESULT=PASS_PVEPRO_V1_BASELINE_CONTINUATION\nNO_MUTATION=true\nHOMELAB_RESULT_CONTRACT={\"version\":1,\"command_id\":\"SUPPORT-260920-PVEPRO-V1-BASELINE-CONTINUATION-READONLY-720R1\",\"status\":\"OK\",\"changes_made\":false,\"rollback_started\":false,\"rollback_restored\":null}\n" + "output": "NEWFI191_AUTH={\"command_id\":\"NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191\",\"decision\":\"HOLD_USA_NETBIRD_FORWARDED_AGENT_TELEGRAM_EGRESS\",\"error_code\":\"SSH_AUTH_DENIED\",\"forwarded_agent\":{\"fingerprints\":[\"SHA256:JMCyBDSD7PKqwwKndzDGAO4Lgm55nEmec9Ssn6QGtKg\",\"SHA256:tfEP9WF58ZcGe5zL/juscxX/sVAeS6fxwwiPjpj2I5U\",\"SHA256:PS+jG8Qun3vviOwZ4A2/ozwro+Jeav/x9VkfvH/d2yI\"],\"present\":true,\"ssh_add_rc\":0},\"hostkey\":{\"expected_match\":true,\"fingerprints\":[\"SHA256:J/5Kp48TdNA/RdlTFGEX4nr71yM6uc5ub5Iahr4xAWE\",\"SHA256:nen1KYo/PIGw45nlakIZpa/SSo/llm3tokCz0hFzboE\",\"SHA256:DXJGwunC5tEVvnC3nRxyayTN8FXmyJcVgf+Oa6udQsY\"]},\"relay\":{\"connection_type\":\"P2P\",\"name\":\"relay.netbird.selfhosted\",\"netbird_ip_sha256\":\"0f61feb58699a097fdfae741ce53e84cd9eae29e8c8d893a0822f20af9231d4c\",\"status\":\"Connected\",\"usa_public_endpoint_confirmed\":true},\"ssh\":{\"accepted_fingerprints\":[],\"error_class\":\"AUTH_DENIED\",\"offered_fingerprints\":[\"SHA256:JMCyBDSD7PKqwwKndzDGAO4Lgm55nEmec9Ssn6QGtKg\",\"SHA256:tfEP9WF58ZcGe5zL/juscxX/sVAeS6fxwwiPjpj2I5U\",\"SHA256:PS+jG8Qun3vviOwZ4A2/ozwro+Jeav/x9VkfvH/d2yI\"],\"rc\":255,\"stderr_sha256\":\"96e972784f367ad113bee81e15345cf73d3a15b106f5857a98cfedf2074363a2\",\"stdout_sha256\":\"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"},\"status\":\"FAIL\",\"tcp22\":true}\nHOMELAB_RESULT_CONTRACT={\"version\":1,\"command_id\":\"NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191\",\"status\":\"FAIL\",\"changes_made\":false,\"rollback_started\":false,\"rollback_restored\":null}\n" } diff --git a/runtime/latest.txt b/runtime/latest.txt index ecdcfef4..ccbfa7ca 100644 --- a/runtime/latest.txt +++ b/runtime/latest.txt @@ -1,22 +1,22 @@ CHAT_OUTPUT_BEGIN -COMMAND_ID=SUPPORT-260920-PVEPRO-V1-BASELINE-CONTINUATION-READONLY-720R1 -STATUS=OK -RC=0 +COMMAND_ID=NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191 +STATUS=FAIL +RC=3 HOST=pve01 MODE=read-only -COMPONENT=pvepro-v1-baseline-continuation-readonly +COMPONENT=newfi-newfdom-telegram214-netbird-usa-forwarded-agent-readonly REFERENCE_REGISTER_CHECK=OK REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66 ERROR_REGISTER_CHECK=OK ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0 -COMMAND_SHA256=5db057f95eaa17a2cd9dc6f722baa09e278b07f4fbf4cbed1e3f42744e7e4284 +COMMAND_SHA256=7c3dadf65cc5f836859b5a49c0eb69fee72025b4bb20a86ea2e284e25188e1a1 DUPLICATE_FAILED_COMMAND_BLOCKED=false EXECUTION_STARTED=true CHANGE_DECLARED=false RESULT_CONTRACT_VALID=true RESULT_CONTRACT_STATUS=NOT_APPLICABLE RESULT_CONTRACT_ERROR=NONE -COMMAND_RC=0 +COMMAND_RC=3 CHANGES_MADE=false ROLLBACK_STARTED=false ROLLBACK_RESTORED=null @@ -24,73 +24,11 @@ MUTATION_OUTCOME=NO_MUTATION SANITIZED=yes SECRETS_INCLUDED=no PRIVATE_ADDRESSES_INCLUDED=no -RAW_EVIDENCE_SHA256=a4ad6491e8a0664a5f0442b527233e5f256a690a536b23ee0f3d69e4b4620992 -SANITIZED_OUTPUT_SHA256=4fba74cd84c317cf0136858f3d64fa80f38be851347aac3bc79216fdbdc7abe4 +RAW_EVIDENCE_SHA256=d5c2a115ff45953643648838f19d31a0b2b7b4c6e1a1a142dead7e426fe2a533 +SANITIZED_OUTPUT_SHA256=d5c2a115ff45953643648838f19d31a0b2b7b4c6e1a1a142dead7e426fe2a533 OUTPUT_BEGIN -PVE01_RELEVANT_ARCHIVE_FILE_COUNT=7 -PVE01_RELEVANT_ARCHIVE_FILES=[{"path":"[XenForo.Info]_language-Russian-(RU)-XF-2.3.10.zip","bytes":298309,"sha256":"68e0308b23a30dadd6399032fbef22e09693220a97a602ee6ef8a8c5492bce6b"},{"path":"[XenForo.Info]_language-Russian-(RU)-XFMG.xml.zip","bytes":19004,"sha256":"ca07af8f88131aa3217fcf1efeeacd20f6af3d97937bce45e202a013103aa78b"},{"path":"[XenForo.Info]_language-Russian-(RU)-XFRM-2.3.5.zip","bytes":13985,"sha256":"ca249fcfc31cd0af5c5a8f1b9bfa7688ae2901eeb7390988d6addc6b5359ea35"},{"path":"[XenForo.Info]_xenForo 2.3.12 Release Edition By xenForo.Info.zip","bytes":23715636,"sha256":"fc5eae1d72abf2597465379ebf5e7426da2449d4956e3be33188c0650811dfc2"},{"path":"[XenForo.Info]_xfes_2.3.11_full.zip","bytes":71079,"sha256":"61acf9377e90dfdf2254b3f32bf2ff7f0af97eb553cc061c9d133cd66682e98d"},{"path":"[XenForo.Info]_xfmg_2.3.11_full.zip","bytes":589096,"sha256":"07062ad308ed0da43b9012a520d0723b52d4c9c9faef02663f4f79eeffa48a52"},{"path":"[XenForo.Info]_xfrm_2.3.11_full.zip","bytes":325192,"sha256":"a7ba29ca6179dd0606c9a6e43096cce2e7575444e8d9c44412afb64d5d298c21"}] -PRIOR_NEWFI_WORKTREE_EXISTS=true -PRIOR_NEWFI_OPERATION_REFERENCES=[{"path":"docs/operations/addons-language.md","sha256":"8ccbeee79e225d5a18cfcd2b186d76c6357608caed7a55fb6c7d06fd2a230a5c","bytes":2707,"key_lines":["# Newfi add-ons and Russian language","## Russian language packs","- Core Russian created `language_id=2`, title `Russian (RU)`, language code `ru-RU` through `XF\\Service\\Language\\ImportService`.","- XFMG and XFRM packs were imported into the same entity with `setOverwriteLanguage()` after their add-ons were installed.","- Accepted phrase counts for language 2: XF `11142`, XFMG `722`, XFRM `464`, total `12328`.","- `defaultLanguageId` was changed through the XenForo Option repository from `1` to `2` only after all three packs passed acceptance.","- English (US), language ID 1, remains installed and user-selectable.","- Staging board remains disabled: `boardActive=0`.","- Board title remains `Newfi Staging`.","- Board URL remains `http://newfi-staging.gram1.ru`.","## Rollback","- Pre-add-on rollback: `/root/newfi-task5-preaddons-20260904T223005Z` on VM211.","- DB backup SHA256: `19e347e3966a9933305acfdd0ce5fb8480b34ab31e23b2ff47f5a46bb9cf7a1b`.","- Public tree backup SHA256: `e6ab5203d3bbfe72089648f3ec36a0c8fae7f7a5292ac7d3893ce8d303f8f29a`.","- Both rollback artifacts are root-owned mode `0600` and passed integrity verification."]},{"path":"docs/operations/backup-restore.md","sha256":"0d0bb33f688f2a44271eaed49b63560619a2442104db886d9c21ec87758f105f","bytes":3166,"key_lines":["# Newfi foundation backup and restore","- Source VM: `211` (`newfi-staging`)","- Canonical sealed state: `/var/lib/homelab-backup/cloud-quorum/vm211/vm211-pve03-20260906T083057Z.json`","- Bounded Cloud-A evidence: `/var/lib/homelab-backup/vm-restore-validation/vm211/vm211-pve03-20260906T083057Z.json`","- Full isolated restore evidence: `/var/lib/homelab-backup/vm-restore-validation/vm211/vm211-pve03-20260906T083057Z-newfi-full.json`","The backup used the current homelab VM cloud-quorum worker/transport contract with a root-only bounded worker copy whose only allowlist extension was VM211 as `pve03/qemu`. The shared worker was not modified.","## Full isolated restore","The same sealed generation was reconstructed from Cloud A and restored with native Proxmox `qmrestore` into temporary VMID `9211`.","- VM9211 was restored stopped.","- Every restored NIC was set to `link_down=1` before boot.","- No application mail path was invoked.","The restored guest proved:","- default XenForo language ID `2`","- language code `ru-RU`","- protected DB/mail configuration permissions","## Restore-attempt RCAs","`NEWFI76` reconstructed the correct bytes and archive SHA but used the temporary basename `archive.vma.zst`. Proxmox `qmrestore` determines archive metadata from the filename and rejected it before restore. Committed-state checks proved no VM9211 residue.","`NEWFI78` then completed a real isolated restore, but its acceptance verifier used a Cyrillic substring test for the language title. XenForo's authoritative restored record was `language_id=2`, `title=Russian (RU)`, `language_code=ru-RU`; therefore that result was a verifier false negative. Cleanup again left no VM9211 residue.","`NEWFI80` uses the authoritative language ID/code contract and records the accepted full restore evidence.","`./scripts/verify-foundation-restore.sh`","The verifier checks strict SEALED state, bounded Cloud-A recovery evidence, accepted full-restore evidence, VM9211/LV absence and performs a fresh remote seal verification."]},{"path":"docs/operations/brand-assets.md","sha256":"9fc0b97c73be6462143edd7cf30c23fe68cdd97ac9441fe11b81651d947ef6f1","bytes":1303,"key_lines":["The user already installed the profile/community icon and the profile banner manually. This checkpoint deliberately does **not** write avatar/profile/banner records or files and does not alter a header logo. Header/theme composition remains for `STYLE199`.","- XenForo favicon style property `publicFaviconUrl` -> `styles/newfi/brand/brand198/newfidom-favicon-32.accef45839db.png`","- XenForo 192x192 PWA style property `publicIconUrl` -> `styles/newfi/brand/brand198/newfidom-pwa-192.db0307c1a668.png`","- XenForo 512x512 PWA style property `publicIconUrlLarge` -> `styles/newfi/brand/brand198/newfidom-pwa-512.39f204179d59.png`","Promotion contract: staging VM211 apply and VM211 loopback/Host HTTP verification, exact staging rollback proof, staging re-apply, Git commit/push, then production VM210 apply and public `https://newfi.ru` desktop/mobile/manifest/static-asset verification. XenForo application state changes use `StyleProperty::updatePropertyValues` via the repository layer; raw SQL mutations are prohibited."]},{"path":"docs/operations/mail.md","sha256":"b7e9e8f05389fb14f452f813a8000050852bcdb6219ce6a423fed053b4292690","bytes":3172,"key_lines":["# Newfi mail operations","The mail-transport portion of Task 6 was accepted on 2026-09-06 for private staging.","This does **not** close Task 6 as a whole. Registration, email-confirmation/anti-spam configuration, the staging security baseline and registration/login/password-reset acceptance remain pending.","- XenForo transport option remains `sendmail`.","- `/usr/sbin/sendmail` resolves to `/usr/bin/msmtp`.","- Debian packages `msmtp` and `msmtp-mta` are installed.","- `/etc/msmtprc` is `root:xfp_newfi` mode `0640`.","- `/etc/msmtprc` retrieves the credential through `passwordeval`; the credential value is not stored in this repository.","- XenForo `contactEmailAddress`: `aleisaev@yandex.ru`, explicitly approved on 2026-09-06.","- The technical/staging administrator email was not changed as part of this mail work.","Exactly one accepted smoke message was sent through the XenForo application mailer:","- Command ID: `NEWFI-260906-MAIL52`.","- Subject: `[NEWFI] mail acceptance NEWFI-260906-MAIL52`.","- XenForo API path: `newMail()` -> `setTo()` -> `setContent()` -> `send(null, false)`.","- The operator separately confirmed that this exact message arrived in the approved Yandex mailbox.","## Rollback evidence","The mail-transport mutation retained rollback evidence under:","`/root/newfi-task6-mail-pre-20260906T065736Z`","- registration and email-confirmation policy;","- `scripts/verify-staging-security.sh`.","Public routing, `boardActive`, bounce/unsubscribe identities, DNS mail policy and unrelated infrastructure remain outside this accepted mail scope."]},{"path":"docs/operations/portal-navigation.md","sha256":"66e03d84ade36af39cf518a51bdd842f0800ef232c5a9676970ce9c65ce32553","bytes":1870,"key_lines":["# Newfi Portal navigation/widgets checkpoint","This checkpoint extends the accepted `Newfi/Portal` staging entrypoint without changing","the closed-staging or public-cutover boundaries.","- Render the already-existing `whats_new_new_posts` widget on the Portal.","- Render the already-existing `xfrm_whats_new_overview_new_resources` widget on the Portal.","and the Portal template only. VM211 applies the source through XenForo's normal rebuild","Before final acceptance, the command proves rollback by restoring the prior Portal template,","Newfi navigation/phrase disappear while the original Portal remains installed. The same","python3 scripts/verify-portal-navigation.py","The verifier chains the accepted content and Portal verifiers, checks the navigation entry,","phrase, existing widget keys, rendered Portal template, zero custom Newfi widget rows,","zero XenForo errors, `boardActive=0`, `indexRoute=portal/`, VM210 absence and the exact","## Rollback","Restore the previous Portal template, remove this add-on's navigation/phrase `_data` files"]},{"path":"docs/operations/portal.md","sha256":"8fa654db0c45d8fbda6b022cc11ad5597dc5543ab98bcee774034d2718cd8708","bytes":1648,"key_lines":["# Newfi Portal staging checkpoint","`Newfi/Portal` is the minimal private-staging landing route for the closed MVP.","- add-on id: `Newfi/Portal`","- public route: `portal`","- public template: `newfi_portal`","- staging `indexRoute`: `portal/`","The Portal is intentionally plain. Navigation/widgets and permanent \u00ab\u0411\u043e\u043b\u044c\u0448\u0430\u044f \u0432\u043e\u0434\u0430\u00bb","Rollback proof before `indexRoute` change:","6. prove no Portal add-on/route/template residue.","## Verification and rollback","Run `python3 scripts/verify-portal-staging.py` from the implementation worktree.","For rollback after this checkpoint, first restore `indexRoute=forums/` through","remove only `src/addons/Newfi/Portal` from VM211 if the source is intentionally withdrawn."]},{"path":"docs/operations/style-staging.md","sha256":"7cc57486e57574ce25fd09e1cb03ffb4fd28954415834c757f32c0ca74df8d09","bytes":2142,"key_lines":["# Newfi staging style checkpoint","This checkpoint creates a dedicated XenForo child style for private staging.","- Title: `Newfi Staging`","- Parent: style `1` (`Default style`)","- Make it the staging `defaultStyleId`","- Keep `indexRoute=portal/`","style is only a safe inheritance container for the later \u00ab\u0411\u043e\u043b\u044c\u0448\u0430\u044f \u0432\u043e\u0434\u0430\u00bb design checkpoint,","The accepted state therefore requires zero child-style rows in `xf_style_property`,","`xf_style_property_group` and `xf_template`.","Creation uses `XF\\Entity\\Style::save()`, the same entity used by the Admin style save flow.","`Style::_postSave()` performs XenForo's rebuild/cache handling.","The staging default is changed only through","`XF\\Repository\\OptionRepository::updateOption('defaultStyleId', ...)`.","Rollback is proven before acceptance with an explicit PHP-process boundary:","1. In PHP process C, restore `defaultStyleId=1` through `OptionRepository`, then end that process.","2. In fresh PHP process D, prove both the DB option and `XF::options()->defaultStyleId` are `1`.","3. Only then delete the child with `XF\\Entity\\Style::delete()`.","4. Prove style count returns to one and all accepted verifiers pass.","5. In a fresh process, re-create the child style and set its actual new ID as `defaultStyleId`.","6. In another fresh process, prove DB and application options agree on the final style ID and run the style verifier.","This process split is required because `XF\\Entity\\Style::_preDelete()` checks the current","application process' cached `options()->defaultStyleId`, not a fresh direct read of `xf_option`.","python3 scripts/verify-style-staging.py"]},{"path":"docs/checkpoints/private-staging-backup-restore.md","sha256":"d8692f662ec16017b4f49c60aa3add6a14c8fab822ab0a9d2272eb20fb9c5e37","bytes":2138,"key_lines":["# Newfi private staging \u2014 fresh backup and full restore gate","Fresh backup command: `NEWFI-260906-FINAL181`","Restore-validation command: `NEWFI-260907-FINAL183`","Sealed state: `/var/lib/homelab-backup/cloud-quorum/vm211/vm211-pve03-20260906T213759Z.json`","Full isolated restore evidence: `/var/lib/homelab-backup/vm-restore-validation/vm211/vm211-pve03-20260906T213759Z-newfi-full.json`","Restored system state after boot convergence: `degraded`","Observed failed units in network-isolated restore: `[\"systemd-networkd-wait-online.service\"]`","- FINAL181 created the fresh VM211 backup and sealed it with Cloud A + Cloud B quorum 2;","- local backup payload was removed after strict seal;","- temporary VM9211 was restored with unique MAC assignment and all restored NICs link-down before boot;","- restored nginx, MariaDB, PHP-FPM, cron and qemu-guest-agent were required active;","- restored system state had to converge to running or degraded;","- restored XenForo application state, add-ons, routes, zero-content invariants, KB, PWA files and protected-file metadata were verified through QGA;","- VM9211, its config, restore LVs and reconstruction work were removed after proof;","- source VM211 remained system-running with zero failed units before and after the restore drill;","This completes the approved **private staging** implementation gate. It does not authorize VM210 creation, production deployment, board enablement, route 998 cutover, or public launch. `SHELL_INCIDENT=OPEN_RCA_UNPROVEN` remains open."]},{"path":"scripts/verify-addons-language.sh","sha256":"c825959b40cb6713aa7932e290d0e1b104ad2e3173d361bf6de617669f0324f0","bytes":4599,"key_lines":["language_rows=$(mariadb --defaults-extra-file=/etc/newfi/db.cnf --batch --skip-column-names -e \"SELECT CONCAT_WS(0x7c,language_id,title,language_code,parent_id,user_selectable) FROM xf_language ORDER BY language_id\")","phrase_rows=$(mariadb --defaults-extra-file=/etc/newfi/db.cnf --batch --skip-column-names -e \"SELECT CONCAT_WS(0x7c,addon_id,COUNT(*)) FROM xf_phrase WHERE language_id=2 GROUP BY addon_id ORDER BY addon_id\")","phrases=$(mariadb --defaults-extra-file=/etc/newfi/db.cnf --batch --skip-column-names -e \"SELECT COUNT(*) FROM xf_phrase WHERE language_id=2\")","expected_languages=$(printf \"1|English (US)|en-US|0|1\\n2|Russian (RU)|ru-RU|0|1\")","printf \"ADDON_ROWS_BEGIN\\n%s\\nADDON_ROWS_END\\nLANGUAGE_ROWS_BEGIN\\n%s\\nLANGUAGE_ROWS_END\\nRU_PHRASE_ROWS_BEGIN\\n%s\\nRU_PHRASE_ROWS_END\\nDEFAULT_LANGUAGE_ID=%s\\nRU_PHRASE_COUNT=%s\\nDB_TABLES=%s\\nBOARD_ROW=%s|%s|%s\\nERROR_LOG_COUNT=%s\\nMANUAL_JOB_COUNT=%s\\n\" \"$addon_rows\" \"$language_rows\" \"$phrase_rows\" \"$default_lang\" \"$phrases\" \"$tables\" \"$board\" \"$title\" \"$url\" \"$errors\" \"$manual\"","test \"$language_rows\" = \"$expected_languages\"","test \"$title\" = \"Newfi Staging\"","test \"$url\" = \"http://newfi-staging.gram1.ru\"","printf \"NEWFI_TASK5_VERIFY=PASS\\n\""]},{"path":"scripts/verify-foundation-restore.sh","sha256":"cc8b821ffd64c8b2d780eb6efaf96f3724230c2bfe50c7db08c4162f79dc2186","bytes":5019,"key_lines":["STATE=/var/lib/homelab-backup/cloud-quorum/vm211/$GEN.json","BOUNDED=/var/lib/homelab-backup/vm-restore-validation/vm211/$GEN.json","FULL=/var/lib/homelab-backup/vm-restore-validation/vm211/${GEN}-newfi-full.json","print(\"STOP=RESTORE_EVIDENCE_INVALID:\"+path)","\"restored_guest_proof\",","and bounded.get(\"schema\")==\"homelab-vm-restore-validation-v1\"","and full.get(\"schema\")==\"newfi-foundation-full-restore-v1\"","and full.get(\"full_restore_proven\") is True","and guest.get(\"default_language_id\")==\"2\"","and guest.get(\"default_language_code\")==\"ru-RU\"","print(\"NEWFI_FOUNDATION_RESTORE_VERIFY=FAIL\")","print(\"NEWFI_FOUNDATION_RESTORE_VERIFY=FAIL_TEST_VM_RESIDUE\")","print(\"NEWFI_FOUNDATION_RESTORE_VERIFY=FAIL_TEST_LV_RESIDUE\")","\"verify-sealed\",","\"pve01-mail-01-crypt:homelab-backups\",","\"pve01-mail-02-crypt:homelab-backups\",","\"/var/lib/homelab-backup/cloud-quorum\"","print(\"NEWFI_FOUNDATION_RESTORE_VERIFY=FAIL_REMOTE_SEAL\")","print(\"NEWFI_FOUNDATION_RESTORE_VERIFY=PASS\")","print(\"FULL_RESTORE_PROVEN=true\")"]},{"path":"scripts/verify-brand-assets.py","sha256":"efaf9bd3af3ec7d28a8ffd3f3ddf88d25f9e76bbd1c5e262e902523716ede6af","bytes":1165,"key_lines":["if cfg['header_logo']!='deferred_to_STYLE199_no_manual_asset_overwrite': raise RuntimeError('logo')","print('NEWFI_BRAND_ASSET_SOURCE_VERIFY=PASS')"]},{"path":"scripts/verify-portal-staging.py","sha256":"07cdf461aa7126a9519b209f431c0dbff093b3984f372fa855bb6bf53920fab9","bytes":5003,"key_lines":["\"src/addons/Newfi/Portal/addon.json\",","\"src/addons/Newfi/Portal/Pub/Controller/Portal.php\",","\"src/addons/Newfi/Portal/Pub/View/Portal.php\",","\"src/addons/Newfi/Portal/_data/routes.xml\",","\"src/addons/Newfi/Portal/_data/templates.xml\",","if b\"PASS\" not in run([str(ROOT/\"scripts/verify-content-structure.sh\")],t=120).stdout:","$a=$app->addOnManager()->getById('Newfi/Portal');","$row=$db->fetchRow(\"SELECT addon_id,active,is_processing,last_pending_action FROM xf_addon WHERE addon_id='Newfi/Portal'\");","'route_rows'=>(int)$db->fetchOne(\"SELECT COUNT(*) FROM xf_route WHERE addon_id='Newfi/Portal' AND route_type='public' AND route_prefix='portal'\"),","'route_controller'=>(string)$db->fetchOne(\"SELECT controller FROM xf_route WHERE addon_id='Newfi/Portal' AND route_type='public' AND route_prefix='portal' LIMIT 1\"),","'template_rows'=>(int)$db->fetchOne(\"SELECT COUNT(*) FROM xf_template WHERE addon_id='Newfi/Portal' AND type='public' AND title='newfi_portal'\"),","'controller_loads'=>class_exists('Newfi\\\\Portal\\\\Pub\\\\Controller\\\\Portal'),","'view_loads'=>class_exists('Newfi\\\\Portal\\\\Pub\\\\View\\\\Portal')","and r[\"route_rows\"]==1 and r[\"route_controller\"]==\"Newfi\\\\Portal:Portal\"","and r[\"template_rows\"]==1 and r[\"index_route\"]==\"portal/\" and r[\"board_active\"]==\"0\"","print(\"NEWFI_PORTAL_VERIFY=\"+json.dumps({\"result\":\"PASS\",\"runtime\":r,\"public_parked_exact\":True,\"vm210_absent\":True},sort_keys=True))"]},{"path":"scripts/verify-style-staging.py","sha256":"2a3bc464da8d0dee93e2fd16a8edfd6a7f750a8d28653d5f5bf77691fb86afad","bytes":4857,"key_lines":["DECL=ROOT/\"config/newfi-style-staging.json\"","\"title\":\"Newfi Staging\",","\"parent_style_id\":1,","\"description\":\"Private staging style container; visual identity intentionally not defined.\",","[str(ROOT/\"scripts/verify-content-structure.sh\")],","[\"/usr/bin/python3\",str(ROOT/\"scripts/verify-portal-staging.py\")],","[\"/usr/bin/python3\",str(ROOT/\"scripts/verify-portal-navigation.py\")]","$styles=$db->fetchAll(\"","SELECT style_id,parent_id,title,description,user_selectable,enable_variations,designer_mode","FROM xf_style","WHERE title='Newfi Staging'","ORDER BY style_id","$style=(count($styles)===1 ? $styles[0] : null);","$id=$style ? (int)$style['style_id'] : 0;","'matching_styles'=>$styles,","'style_count'=>(int)$db->fetchOne(\"SELECT COUNT(*) FROM xf_style\"),","'default_style_id'=>(string)$db->fetchOne(\"SELECT option_value FROM xf_option WHERE option_id='defaultStyleId'\"),","'default_style_options'=>(string)$app->options()->defaultStyleId,","'property_rows'=>$id ? (int)$db->fetchOne(\"SELECT COUNT(*) FROM xf_style_property WHERE style_id=?\", $id) : -1,","'property_group_rows'=>$id ? (int)$db->fetchOne(\"SELECT COUNT(*) FROM xf_style_property_group WHERE style_id=?\", $id) : -1,","'template_rows'=>$id ? (int)$db->fetchOne(\"SELECT COUNT(*) FROM xf_template WHERE style_id=?\", $id) : -1,","if len(r[\"matching_styles\"])!=1:","raise RuntimeError(\"style-match\")","s=r[\"matching_styles\"][0]","sid=int(s[\"style_id\"])"]},{"path":"scripts/verify-web-foundation.sh","sha256":"f7ad539ed2b5c3d7f09aaea0e84b82679a608b60d105271bcb62f0443bb2d84b","bytes":3787,"key_lines":["NGINX_EXPECTED=$(sha256sum \"$ROOT/deploy/nginx/newfi-staging.conf\" | awk '{print $1}')","FPM_EXPECTED=$(sha256sum \"$ROOT/deploy/php/newfi-staging-pool.conf\" | awk '{print $1}')","probe=/var/www/forums/newfi/public/__newfi_verify.txt","trap \"rm -f \\\"$probe\\\" /run/newfi-web-verify.out\" EXIT","printf \"NEWFI_WEB_VERIFY=PASS\\n\" > \"$probe\"","code=$(curl -sS -H \"Host: newfi-staging.gram1.ru\" -o /run/newfi-web-verify.out -w \"%{http_code}\" http://127.0.0.1/__newfi_verify.txt)","grep -qx \"NEWFI_WEB_VERIFY=PASS\" /run/newfi-web-verify.out","for path in /src/XF.php /internal_data/test.php /install/ /data/test.php /library/test.php; do code=$(curl -sS -o /dev/null -w \"%{http_code}\" -H \"Host: newfi-staging.gram1.ru\" \"http://127.0.0.1$path\"); test \"$code\" = 403; done","printf 'NEWFI_WEB_FOUNDATION_VERIFY=PASS\\n'"]}] -PVE01_OPERATION_DOC_MATCHES=[{"path":"/etc/pve/HOMELAB_FULL_HANDOFF_HISTORICAL_2026-07-09.md","sha256":"40913559857c212486760d696140e746f7b97fbdde7a226956a5ac3cfe6eb1df","hits":["6. External Homepage link `https://aleisaevn.netcraze.pro:5083/` is classified as an external link, not a homelab-managed service.","PASSWORD|TOKEN|SECRET|PRIVATE|KEY|ROOT_USER|ROOT_PASSWORD|ENCRYPTION_KEY|AUTH|SMTP|MSMTP|COOKIE|SESSION|AGE-SECRET|\\.env|[SENSITIVE_PATH]|[SENSITIVE_PATH]|[SENSITIVE_FILE]","STATUS=OK TS=2026-07-09T16:46:31Z TYPE=service-readiness-final BAD=0 SERVICE=paperless HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://paper.gram1.ru STATE=app:running/healthy,postgres:running,redis:running","- Route/Homepage/Kuma OK.","STATUS=OK TS=2026-07-09T16:50:21Z TYPE=service-readiness-final BAD=0 SERVICE=memos HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://memos.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T17:40:57Z TYPE=service-readiness-final BAD=0 SERVICE=linkding HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://linkding.vpn.gram1.ru STATE=running/healthy","STATUS=OK TS=2026-07-09T17:47:41Z TYPE=healthchecks-canonical-domain-repair BAD=0 SERVICE=healthchecks CANONICAL_URL=https://checks.vpn.gram1.ru OLD_ALIAS=https://healthchecks.vpn.gram1.ru OLD_ALIAS_DEFAULT_PAGE=1 HOMEPAGE=OK KUMA=OK BESZEL_NTFY_KUMA=OK LOGS=OK NOTE=service-readiness-count-unchanged","STATUS=OK TS=2026-07-09T17:47:41Z TYPE=service-readiness-final BAD=0 SERVICE=healthchecks HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://checks.vpn.gram1.ru STATE=running/healthy NOTE=canonical-domain-corrected-from-healthchecks-vpn-to-checks-vpn","STATUS=OK TS=2026-07-09T17:55:47Z TYPE=service-readiness-final BAD=0 SERVICE=vikunja HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://vikunja.vpn.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T18:01:02Z TYPE=service-readiness-final BAD=0 SERVICE=bookstack HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://bookstack.vpn.gram1.ru STATE=app:running/nohealth,db:running/nohealth","STATUS=OK TS=2026-07-09T18:13:21Z TYPE=service-readiness-final BAD=0 SERVICE=stirling-pdf HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://pdf.vpn.gram1.ru STATE=running/healthy","STATUS=OK TS=2026-07-09T18:19:10Z TYPE=service-readiness-final BAD=0 SERVICE=jellyfin HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://jellyfin.vpn.gram1.ru STATE=running/healthy","STATUS=OK TS=2026-07-09T18:25:21Z TYPE=service-readiness-final BAD=0 SERVICE=audiobookshelf HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://audiobooks.vpn.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T18:57:16Z TYPE=service-readiness-final BAD=0 SERVICE=calibre-web HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://books.vpn.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T19:07:39Z TYPE=service-readiness-final BAD=0 SERVICE=homeassistant HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://homeassistant.vpn.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T19:23:55Z TYPE=service-readiness-final BAD=0 SERVICE=it-tools HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://it-tools.vpn.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T19:32:34Z TYPE=service-readiness-final BAD=0 SERVICE=karakeep HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://karakeep.vpn.gram1.ru STATE=app:running/healthy,meilisearch:running/nohealth,chrome:running/nohealth","STATUS=OK TS=2026-07-09T19:42:26Z TYPE=service-readiness-final BAD=0 SERVICE=n8n HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://n8n.vpn.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T19:50:17Z TYPE=service-readiness-final BAD=0 SERVICE=node-red HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://node-red.vpn.gram1.ru STATE=running/healthy","STATUS=OK TS=2026-07-09T19:59:09Z TYPE=service-readiness-final BAD=0 SERVICE=syncthing HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://syncthing.vpn.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T20:12:53Z TYPE=service-readiness-final BAD=0 SERVICE=immich HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://photos.gram1.ru STATE=server:running/healthy,postgres:running/healthy,machine-learning:running/healthy,redis:running/healthy","STATUS=OK TS=2026-07-09T20:45:50Z TYPE=service-readiness-final BAD=0 SERVICE=nextcloud HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK URL=https://nc.gram1.ru STATE=vm150:running,nextcloud-status:installed-maintenance-false,turn:monitored","STATUS=OK TS=2026-07-09T20:55:37Z TYPE=service-readiness-final BAD=0 SERVICE=dns1 HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK CONFIG_SYNC=OK BACKUP_SLA=OK ALERTING=OK URL=https://dns1.vpn.gram1.ru STATE=adguard-ui:monitored,dns-tcp:monitored,unbound:monitored","- Homepage card OK.","STATUS=OK TS=2026-07-09T20:55:37Z TYPE=service-readiness-final BAD=0 SERVICE=dns2 HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK CONFIG_SYNC=OK BACKUP_SLA=OK ALERTING=OK URL=https://dns2.vpn.gram1.ru STATE=adguard-ui:monitored,dns-tcp:monitored,unbound:monitored","- Homepage card OK.","## 47. homepage","STATUS=OK TS=2026-07-09T20:55:37Z TYPE=service-readiness-final BAD=0 SERVICE=homepage HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK URL=https://home.gram1.ru STATE=container:running/healthy,config:backed-by-dockge-stacks","- Homepage container `running/healthy`.","- Kuma monitor ID 16 `Homepage HTTPS` green."]},{"path":"/etc/pve/HOMEPAGE_BACKUP_COVERAGE_MATRIX.md","sha256":"b0c75b5656063afdfd7db57ffd3450098b27e75335eab78c9239bda2815887ae","hits":["# HOMEPAGE_BACKUP_COVERAGE_MATRIX","Scope: active Homepage cards with non-empty href only.","| Homepage | https://home.gram1.ru | 190 | 4 | 96 | EVIDENCE_FOUND_REVIEW |"]},{"path":"/etc/pve/31_HOMELAB_REFERENCE.md","sha256":"5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66","hits":["- Homepage/Prometheus retired references absent; Uptime Kuma orphan extra_hosts removed.","HEALTH_NOT_OK item=homepage-service-catalog-slo.txt line=STATUS=WARN","- homepage.vpn.gram1.ru -> http://127.0.0.1:3000, cert=32.","- homepage.","- Admin/dashboard: homepage, dockge, netbox, dozzle, NPMplus VPN admin.","- Homepage: 127.0.0.1:3000.","- Other observed WARN backlog files include container-image-lifecycle-slo, cron-job-monitoring-slo, direct-heartbeat-pilot-readiness, healthchecks-heartbeat-coverage, healthchecks-job-coverage, healthchecks-job-monitoring-slo, homepage-service-catalog-slo, ingress-dns-route-slo, observability-health-surface-slo and security-vulnerability-slo.","| home.gram1.ru | http://127.0.0.1:3000 | edge-vm / homepage | homepage container, dashboard route |","| homepage.vpn.gram1.ru | http://127.0.0.1:3000 | homepage |","- Discovery proof records DNS, HTTPS/TLS headers, reverse-proxy candidates, compose files, domain references and homepage config candidates without printing secrets.","- Home portal gap analysis was collected for gethomepage/homepage behind npmplus.","- Proof records Homepage config hashes, redacted current cards/bookmarks, current URLs, npmplus route lines, local web-port probes and known service container candidates.","- Home portal card/API-error analysis was collected before editing Homepage.","- Proof records current card URLs/titles, redacted widget config, redacted Homepage log errors, NPMPlus internal route files/routes and candidate public/VPN cards.","- Homepage services.yaml was backed up, duplicate VPN cards were removed where a non-VPN card existed, and missing web cards for NetBird, Mail and Webmail were added without VPN suffix in the card names.","- Homepage container was restarted and portal/card URLs were checked.","- Corrected Homepage apply removed duplicate VPN cards where a non-VPN card existed and added NetBird, Mail and Webmail cards with non-VPN names.","- Proof checks portal HTTP status, Homepage container state, required cards, duplicate VPN card pairs, current card URLs, redacted API-error logs and widget configuration.","- Homepage API error root-cause analysis was collected after the UI showed API errors.","- Current evidence points to the Open-Meteo/weather widget timing out from Homepage, separate from service cards.","- HTTP 200 for the portal is not sufficient for UI closure when Homepage logs still contain API errors.","- Open-Meteo/weather widget was disabled after root-cause analysis showed Homepage API errors from api.open-meteo.com timeouts.","- Portal closure now requires current Homepage API-error logs to be zero after restart/reload.","- Audit extracts current Homepage href URLs and checks whether each opens with an acceptable HTTP status.","- Explicit VPN duplicate cards were removed from Homepage with a short transparent perl edit: Homepage VPN, Authentik VPN, Gitea VPN and Uptime Kuma VPN.","- Remaining Homepage duplicate/VPN/router occurrences were inspected after corrected cleanup still reported REVIEW.","- Homepage duplicate cleanup was rechecked against active config files only, excluding logs and backup files.","- Active Homepage services/bookmarks files were cleaned from semantic VPN duplicate cards and old router URL references.","- Removed targets: Homepage VPN, Authentik VPN, Gitea VPN and Uptime Kuma VPN, plus matching vpn.gram1.ru duplicate URLs.","- Analysis checks URL body fingerprints, NPMPlus route config matches, service container candidates and Homepage card lines."]},{"path":"/etc/pve/HOMELAB_FULL_HANDOFF_CURRENT.md","sha256":"82a6060ccc216849c55790a3489ef157d5551a0c7cef0c5ec9abd35f569c7940","hits":["3. Add a read-only observer status card to Homepage or cluster-admin webpanel.","6. External Homepage link `https://aleisaevn.netcraze.pro:5083/` is classified as an external link, not a homelab-managed service.","PASSWORD|TOKEN|SECRET|PRIVATE|KEY|ROOT_USER|ROOT_PASSWORD|ENCRYPTION_KEY|AUTH|SMTP|MSMTP|COOKIE|SESSION|AGE-SECRET|\\.env|[SENSITIVE_PATH]|[SENSITIVE_PATH]|[SENSITIVE_FILE]","STATUS=OK TS=2026-07-09T16:46:31Z TYPE=service-readiness-final BAD=0 SERVICE=paperless HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://paper.gram1.ru STATE=app:running/healthy,postgres:running,redis:running","- Route/Homepage/Kuma OK.","STATUS=OK TS=2026-07-09T16:50:21Z TYPE=service-readiness-final BAD=0 SERVICE=memos HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://memos.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T17:40:57Z TYPE=service-readiness-final BAD=0 SERVICE=linkding HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://linkding.vpn.gram1.ru STATE=running/healthy","STATUS=OK TS=2026-07-09T17:47:41Z TYPE=healthchecks-canonical-domain-repair BAD=0 SERVICE=healthchecks CANONICAL_URL=https://checks.vpn.gram1.ru OLD_ALIAS=https://healthchecks.vpn.gram1.ru OLD_ALIAS_DEFAULT_PAGE=1 HOMEPAGE=OK KUMA=OK BESZEL_NTFY_KUMA=OK LOGS=OK NOTE=service-readiness-count-unchanged","STATUS=OK TS=2026-07-09T17:47:41Z TYPE=service-readiness-final BAD=0 SERVICE=healthchecks HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://checks.vpn.gram1.ru STATE=running/healthy NOTE=canonical-domain-corrected-from-healthchecks-vpn-to-checks-vpn","STATUS=OK TS=2026-07-09T17:55:47Z TYPE=service-readiness-final BAD=0 SERVICE=vikunja HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://vikunja.vpn.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T18:01:02Z TYPE=service-readiness-final BAD=0 SERVICE=bookstack HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://bookstack.vpn.gram1.ru STATE=app:running/nohealth,db:running/nohealth","STATUS=OK TS=2026-07-09T18:13:21Z TYPE=service-readiness-final BAD=0 SERVICE=stirling-pdf HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://pdf.vpn.gram1.ru STATE=running/healthy","STATUS=OK TS=2026-07-09T18:19:10Z TYPE=service-readiness-final BAD=0 SERVICE=jellyfin HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://jellyfin.vpn.gram1.ru STATE=running/healthy","STATUS=OK TS=2026-07-09T18:25:21Z TYPE=service-readiness-final BAD=0 SERVICE=audiobookshelf HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://audiobooks.vpn.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T18:57:16Z TYPE=service-readiness-final BAD=0 SERVICE=calibre-web HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://books.vpn.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T19:07:39Z TYPE=service-readiness-final BAD=0 SERVICE=homeassistant HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://homeassistant.vpn.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T19:23:55Z TYPE=service-readiness-final BAD=0 SERVICE=it-tools HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://it-tools.vpn.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T19:32:34Z TYPE=service-readiness-final BAD=0 SERVICE=karakeep HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://karakeep.vpn.gram1.ru STATE=app:running/healthy,meilisearch:running/nohealth,chrome:running/nohealth","STATUS=OK TS=2026-07-09T19:42:26Z TYPE=service-readiness-final BAD=0 SERVICE=n8n HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://n8n.vpn.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T19:50:17Z TYPE=service-readiness-final BAD=0 SERVICE=node-red HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://node-red.vpn.gram1.ru STATE=running/healthy","STATUS=OK TS=2026-07-09T19:59:09Z TYPE=service-readiness-final BAD=0 SERVICE=syncthing HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://syncthing.vpn.gram1.ru STATE=running/nohealth","STATUS=OK TS=2026-07-09T20:12:53Z TYPE=service-readiness-final BAD=0 SERVICE=immich HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK LOGS=OK URL=https://photos.gram1.ru STATE=server:running/healthy,postgres:running/healthy,machine-learning:running/healthy,redis:running/healthy","STATUS=OK TS=2026-07-09T20:45:50Z TYPE=service-readiness-final BAD=0 SERVICE=nextcloud HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK RUNBOOK=OK URL=https://nc.gram1.ru STATE=vm150:running,nextcloud-status:installed-maintenance-false,turn:monitored","STATUS=OK TS=2026-07-09T20:55:37Z TYPE=service-readiness-final BAD=0 SERVICE=dns1 HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK CONFIG_SYNC=OK BACKUP_SLA=OK ALERTING=OK URL=https://dns1.vpn.gram1.ru STATE=adguard-ui:monitored,dns-tcp:monitored,unbound:monitored","- Homepage card OK.","STATUS=OK TS=2026-07-09T20:55:37Z TYPE=service-readiness-final BAD=0 SERVICE=dns2 HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK CONFIG_SYNC=OK BACKUP_SLA=OK ALERTING=OK URL=https://dns2.vpn.gram1.ru STATE=adguard-ui:monitored,dns-tcp:monitored,unbound:monitored","- Homepage card OK.","## 47. homepage","STATUS=OK TS=2026-07-09T20:55:37Z TYPE=service-readiness-final BAD=0 SERVICE=homepage HOMEPAGE=OK NPMPLUS=OK KUMA=OK HEALTH=OK PUBLIC=OK BACKUP=OK OFFHOST=OK RESTORE=OK BACKUP_SLA=OK ALERTING=OK URL=https://home.gram1.ru STATE=container:running/healthy,config:backed-by-dockge-stacks","- Homepage container `running/healthy`."]},{"path":"/etc/pve/HOMELAB_CLUSTER_BACKLOG.md","sha256":"9bcf7d68af10738179b923e6d870e692b4404db55b3ceccc2170ba4f525baf1f","hits":["- Finish Homepage final validation: YAML, siteMonitor, links, no API errors.","- Build Homepage link validator: HTTP status + not NPMPlus default page.","- Maintain backup coverage matrix for all Homepage services.","- Add/verify restore dry-runs for Vaultwarden, Gitea, Grafana, Alertmanager, NPMplus, Homepage, NetBox, Paperless, Memos, Nextcloud, Immich, Jellyfin, BookStack, Vikunja, SearXNG, AdGuard DNS1/DNS2 and other Homepage services.","- Back up NPMPlus config, certificates and Homepage config.","- Create disaster recovery runbooks for edge-vm, pve01, router config, NPMPlus/Homepage and Nextcloud VM.","- Add blackbox-style checks for Homepage cards.","- Build one dashboard for backup, restore, Homepage, Prometheus, Alertmanager, cloud quota and timers.","## P2 Homepage UX","- Apply siteMonitor policy carefully; Router/Homepage/NPMplus/Public Domain are special cases.","1. Finish Homepage final validation.","3. Build backup coverage matrix for all Homepage services.","5. Add Homepage blackbox checks."]},{"path":"/etc/pve/HOMEPAGE_BACKUP_GAP_CLASSIFICATION.md","sha256":"7536d78738a7ab30e45b6a8f42cf4b32b79793b321ae0825158da999d6a2adda","hits":["# HOMEPAGE_BACKUP_GAP_CLASSIFICATION","Goal: every Homepage card must be classified and either covered, explicitly stateless/config-only, or closed with backup+restore+health evidence.","- OPEN becomes CLOSED only when evidence file/proof exists and HOMEPAGE_BACKUP_COVERAGE_MATRIX.md is updated.","- Existing backup coverage must be mapped by exact service name/path, not guessed from fuzzy grep counts."]},{"path":"/etc/pve/HOMELAB_ASSISTANT_ERROR_REGISTER.md","sha256":"3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0","hits":["- Rule: home portal closure requires current Homepage API-error logs to be zero after restart/reload, not only HTTP 200.","- If Homepage UI shows API error or logs contain current httpProxy/API timeout errors, the portal is REVIEW until the widget/API cause is disabled or fixed.","- Rule: Homepage cleanup validation must check active config files only, not logs or backup files.","- Active files are services.yaml, bookmarks.yaml, widgets.yaml, settings.yaml and docker.yaml under /opt/stacks/homepage/config.","- Rule: Homepage link validation must not treat HTTP 200 as success if the body is the NPMPlus default \u201cCongratulations\u201d / host-not-set-up page.","- Context: attempted Netcraze router ACL apply through SSH stdin/multiline for Homepage Moscow Router monitor fix.","- Context: proof 400 tested Moscow router HTTPS monitor from Homepage container with custom Node lookup callback.","- Context: Moscow Router Homepage monitor after ACL fix.","- Impact: Homepage siteMonitor cannot be made green via direct router HTTP URL until router web service allows the Bridge1/Proxmox/protected segment or an explicit safe monitor endpoint is used.","- Context: Moscow Router Homepage siteMonitor attempt using http://:5080.","- Evidence: proof 405 showed route to via Docker bridge and Homepage container ECONNRESET.","- Impact: do not use directly as Homepage siteMonitor from edge-vm.","- Mitigation: use dedicated edge-vm health endpoint that checks router TCP :5080 and returns HTTP 200/503 for Homepage.","## HOMEPAGE_ROUTER_MOSCOW_YAML_TITLE_SHAPE_MISMATCH_20260701","- Context: applying Moscow Router Homepage siteMonitor health endpoint.","- Mistake: assistant apply script matched only property-style cards with `title`, but active Homepage YAML can use service-name-key style like `- Service Name:`.","## HOMEPAGE_ROUTER_MOSCOW_APPLY_SCRIPT_SYNTAX_ERROR_20260701","- Context: applying Moscow Router Homepage health endpoint.","- Evidence: proof 408 showed SyntaxError in /tmp/homepage-router-moscow-apply-fixed.py.","- Actual impact: YAML was not changed, so Homepage green dot could not appear.","## MSMTP_SECRET_SOURCE_PARSE_ERROR_576_20260701","- Context: proof 576 installed msmtp but sendmail auth test failed.","- Issue: [SENSITIVE_PATH] was sourced as shell, but SMTP password contained shell-special characters; source failed and auth used an invalid/truncated secret path.","- Impact: msmtp package installed, but mail sending was not proven working.","- Rule: never source SMTP secret files containing arbitrary passwords; store password base64 and use msmtp passwordeval helper accessible to www-data.","## FORUM_MSMTP_MAIL_TRANSPORT_STILL_FAILING_20260701","- Context: attempted to fix msmtp config with passwordeval helper.","- Context: SMTP password was exposed in terminal output during failed msmtp setup.","- Context: forum-prod SMTP/msmtp test used invalid or compromised credentials and triggered Mailcow netfilter warnings/ban for 95.84.154.183.","- Action: remove forum-prod msmtp secret/config files so XenForo cannot keep retrying broken SMTP auth."]},{"path":"/root/HOMELAB_ASSISTANT_ERROR_REGISTER.md","sha256":"ad60bb9478432540af04df8616e7526967c0dc88d79373c041ba0a27c99e271d","hits":["- Rule: home portal closure requires current Homepage API-error logs to be zero after restart/reload, not only HTTP 200.","- If Homepage UI shows API error or logs contain current httpProxy/API timeout errors, the portal is REVIEW until the widget/API cause is disabled or fixed.","- Rule: Homepage cleanup validation must check active config files only, not logs or backup files.","- Active files are services.yaml, bookmarks.yaml, widgets.yaml, settings.yaml and docker.yaml under /opt/stacks/homepage/config.","- Rule: Homepage link validation must not treat HTTP 200 as success if the body is the NPMPlus default \u201cCongratulations\u201d / host-not-set-up page.","- Context: attempted Netcraze router ACL apply through SSH stdin/multiline for Homepage Moscow Router monitor fix.","- Context: proof 400 tested Moscow router HTTPS monitor from Homepage container with custom Node lookup callback.","- Context: Moscow Router Homepage monitor after ACL fix.","- Impact: Homepage siteMonitor cannot be made green via direct router HTTP URL until router web service allows the Bridge1/Proxmox/protected segment or an explicit safe monitor endpoint is used.","- Context: Moscow Router Homepage siteMonitor attempt using http://:5080.","- Evidence: proof 405 showed route to via Docker bridge and Homepage container ECONNRESET.","- Impact: do not use directly as Homepage siteMonitor from edge-vm.","- Mitigation: use dedicated edge-vm health endpoint that checks router TCP :5080 and returns HTTP 200/503 for Homepage.","## HOMEPAGE_ROUTER_MOSCOW_YAML_TITLE_SHAPE_MISMATCH_20260701","- Context: applying Moscow Router Homepage siteMonitor health endpoint.","- Mistake: assistant apply script matched only property-style cards with `title`, but active Homepage YAML can use service-name-key style like `- Service Name:`.","## HOMEPAGE_ROUTER_MOSCOW_APPLY_SCRIPT_SYNTAX_ERROR_20260701","- Context: applying Moscow Router Homepage health endpoint.","- Evidence: proof 408 showed SyntaxError in /tmp/homepage-router-moscow-apply-fixed.py.","- Actual impact: YAML was not changed, so Homepage green dot could not appear.","## MSMTP_SECRET_SOURCE_PARSE_ERROR_576_20260701","- Context: proof 576 installed msmtp but sendmail auth test failed.","- Issue: [SENSITIVE_PATH] was sourced as shell, but SMTP password contained shell-special characters; source failed and auth used an invalid/truncated secret path.","- Impact: msmtp package installed, but mail sending was not proven working.","- Rule: never source SMTP secret files containing arbitrary passwords; store password base64 and use msmtp passwordeval helper accessible to www-data.","## FORUM_MSMTP_MAIL_TRANSPORT_STILL_FAILING_20260701","- Context: attempted to fix msmtp config with passwordeval helper.","- Context: SMTP password was exposed in terminal output during failed msmtp setup.","- Context: forum-prod SMTP/msmtp test used invalid or compromised credentials and triggered Mailcow netfilter warnings/ban for 95.84.154.183.","- Action: remove forum-prod msmtp secret/config files so XenForo cannot keep retrying broken SMTP auth."]},{"path":"/root/31_HOMELAB_REFERENCE.before-cr0079-20260817T052826Z.md","sha256":"79d217c07b34ccf6e2e30742ddf675afd7321eb4c6fde4086d5092688d96b424","hits":["HEALTH_NOT_OK item=homepage-service-catalog-slo.txt line=STATUS=WARN","- homepage.vpn.gram1.ru -> http://127.0.0.1:3000, cert=32.","- homepage.","- Admin/dashboard: homepage, dockge, netbox, dozzle, NPMplus VPN admin.","- Homepage: 127.0.0.1:3000.","- Other observed WARN backlog files include container-image-lifecycle-slo, cron-job-monitoring-slo, direct-heartbeat-pilot-readiness, healthchecks-heartbeat-coverage, healthchecks-job-coverage, healthchecks-job-monitoring-slo, homepage-service-catalog-slo, ingress-dns-route-slo, observability-health-surface-slo and security-vulnerability-slo.","| home.gram1.ru | http://127.0.0.1:3000 | edge-vm / homepage | homepage container, dashboard route |","| homepage.vpn.gram1.ru | http://127.0.0.1:3000 | homepage |","- Discovery proof records DNS, HTTPS/TLS headers, reverse-proxy candidates, compose files, domain references and homepage config candidates without printing secrets.","- Home portal gap analysis was collected for gethomepage/homepage behind npmplus.","- Proof records Homepage config hashes, redacted current cards/bookmarks, current URLs, npmplus route lines, local web-port probes and known service container candidates.","- Home portal card/API-error analysis was collected before editing Homepage.","- Proof records current card URLs/titles, redacted widget config, redacted Homepage log errors, NPMPlus internal route files/routes and candidate public/VPN cards.","- Homepage services.yaml was backed up, duplicate VPN cards were removed where a non-VPN card existed, and missing web cards for NetBird, Mail and Webmail were added without VPN suffix in the card names.","- Homepage container was restarted and portal/card URLs were checked.","- Corrected Homepage apply removed duplicate VPN cards where a non-VPN card existed and added NetBird, Mail and Webmail cards with non-VPN names.","- Proof checks portal HTTP status, Homepage container state, required cards, duplicate VPN card pairs, current card URLs, redacted API-error logs and widget configuration.","- Homepage API error root-cause analysis was collected after the UI showed API errors.","- Current evidence points to the Open-Meteo/weather widget timing out from Homepage, separate from service cards.","- HTTP 200 for the portal is not sufficient for UI closure when Homepage logs still contain API errors.","- Open-Meteo/weather widget was disabled after root-cause analysis showed Homepage API errors from api.open-meteo.com timeouts.","- Portal closure now requires current Homepage API-error logs to be zero after restart/reload.","- Audit extracts current Homepage href URLs and checks whether each opens with an acceptable HTTP status.","- Explicit VPN duplicate cards were removed from Homepage with a short transparent perl edit: Homepage VPN, Authentik VPN, Gitea VPN and Uptime Kuma VPN.","- Remaining Homepage duplicate/VPN/router occurrences were inspected after corrected cleanup still reported REVIEW.","- Homepage duplicate cleanup was rechecked against active config files only, excluding logs and backup files.","- Active Homepage services/bookmarks files were cleaned from semantic VPN duplicate cards and old router URL references.","- Removed targets: Homepage VPN, Authentik VPN, Gitea VPN and Uptime Kuma VPN, plus matching vpn.gram1.ru duplicate URLs.","- Analysis checks URL body fingerprints, NPMPlus route config matches, service container candidates and Homepage card lines.","- Active Homepage URL: https://home.gram1.ru."]},{"path":"/root/31_HOMELAB_REFERENCE.before-cr0080-cutover-20260817T080345Z.md","sha256":"87f3e9b362524c9f3ff61b0afe26332f71b5f5f6a1c39bb3a1d31d567c4e8aa5","hits":["HEALTH_NOT_OK item=homepage-service-catalog-slo.txt line=STATUS=WARN","- homepage.vpn.gram1.ru -> http://127.0.0.1:3000, cert=32.","- homepage.","- Admin/dashboard: homepage, dockge, netbox, dozzle, NPMplus VPN admin.","- Homepage: 127.0.0.1:3000.","- Other observed WARN backlog files include container-image-lifecycle-slo, cron-job-monitoring-slo, direct-heartbeat-pilot-readiness, healthchecks-heartbeat-coverage, healthchecks-job-coverage, healthchecks-job-monitoring-slo, homepage-service-catalog-slo, ingress-dns-route-slo, observability-health-surface-slo and security-vulnerability-slo.","| home.gram1.ru | http://127.0.0.1:3000 | edge-vm / homepage | homepage container, dashboard route |","| homepage.vpn.gram1.ru | http://127.0.0.1:3000 | homepage |","- Discovery proof records DNS, HTTPS/TLS headers, reverse-proxy candidates, compose files, domain references and homepage config candidates without printing secrets.","- Home portal gap analysis was collected for gethomepage/homepage behind npmplus.","- Proof records Homepage config hashes, redacted current cards/bookmarks, current URLs, npmplus route lines, local web-port probes and known service container candidates.","- Home portal card/API-error analysis was collected before editing Homepage.","- Proof records current card URLs/titles, redacted widget config, redacted Homepage log errors, NPMPlus internal route files/routes and candidate public/VPN cards.","- Homepage services.yaml was backed up, duplicate VPN cards were removed where a non-VPN card existed, and missing web cards for NetBird, Mail and Webmail were added without VPN suffix in the card names.","- Homepage container was restarted and portal/card URLs were checked.","- Corrected Homepage apply removed duplicate VPN cards where a non-VPN card existed and added NetBird, Mail and Webmail cards with non-VPN names.","- Proof checks portal HTTP status, Homepage container state, required cards, duplicate VPN card pairs, current card URLs, redacted API-error logs and widget configuration.","- Homepage API error root-cause analysis was collected after the UI showed API errors.","- Current evidence points to the Open-Meteo/weather widget timing out from Homepage, separate from service cards.","- HTTP 200 for the portal is not sufficient for UI closure when Homepage logs still contain API errors.","- Open-Meteo/weather widget was disabled after root-cause analysis showed Homepage API errors from api.open-meteo.com timeouts.","- Portal closure now requires current Homepage API-error logs to be zero after restart/reload.","- Audit extracts current Homepage href URLs and checks whether each opens with an acceptable HTTP status.","- Explicit VPN duplicate cards were removed from Homepage with a short transparent perl edit: Homepage VPN, Authentik VPN, Gitea VPN and Uptime Kuma VPN.","- Remaining Homepage duplicate/VPN/router occurrences were inspected after corrected cleanup still reported REVIEW.","- Homepage duplicate cleanup was rechecked against active config files only, excluding logs and backup files.","- Active Homepage services/bookmarks files were cleaned from semantic VPN duplicate cards and old router URL references.","- Removed targets: Homepage VPN, Authentik VPN, Gitea VPN and Uptime Kuma VPN, plus matching vpn.gram1.ru duplicate URLs.","- Analysis checks URL body fingerprints, NPMPlus route config matches, service container candidates and Homepage card lines.","- Active Homepage URL: https://home.gram1.ru."]},{"path":"/root/31_HOMELAB_REFERENCE.md","sha256":"30dd35bca4094a82dda70b82f0e1714accbf688479ea320bd311d6de63dd4622","hits":["HEALTH_NOT_OK item=homepage-service-catalog-slo.txt line=STATUS=WARN","- homepage.vpn.gram1.ru -> http://127.0.0.1:3000, cert=32.","- homepage.","- Admin/dashboard: homepage, dockge, netbox, dozzle, NPMplus VPN admin.","- Homepage: 127.0.0.1:3000.","- Other observed WARN backlog files include container-image-lifecycle-slo, cron-job-monitoring-slo, direct-heartbeat-pilot-readiness, healthchecks-heartbeat-coverage, healthchecks-job-coverage, healthchecks-job-monitoring-slo, homepage-service-catalog-slo, ingress-dns-route-slo, observability-health-surface-slo and security-vulnerability-slo.","| home.gram1.ru | http://127.0.0.1:3000 | edge-vm / homepage | homepage container, dashboard route |","| homepage.vpn.gram1.ru | http://127.0.0.1:3000 | homepage |","- Discovery proof records DNS, HTTPS/TLS headers, reverse-proxy candidates, compose files, domain references and homepage config candidates without printing secrets.","- Home portal gap analysis was collected for gethomepage/homepage behind npmplus.","- Proof records Homepage config hashes, redacted current cards/bookmarks, current URLs, npmplus route lines, local web-port probes and known service container candidates.","- Home portal card/API-error analysis was collected before editing Homepage.","- Proof records current card URLs/titles, redacted widget config, redacted Homepage log errors, NPMPlus internal route files/routes and candidate public/VPN cards.","- Homepage services.yaml was backed up, duplicate VPN cards were removed where a non-VPN card existed, and missing web cards for NetBird, Mail and Webmail were added without VPN suffix in the card names.","- Homepage container was restarted and portal/card URLs were checked.","- Corrected Homepage apply removed duplicate VPN cards where a non-VPN card existed and added NetBird, Mail and Webmail cards with non-VPN names.","- Proof checks portal HTTP status, Homepage container state, required cards, duplicate VPN card pairs, current card URLs, redacted API-error logs and widget configuration.","- Homepage API error root-cause analysis was collected after the UI showed API errors.","- Current evidence points to the Open-Meteo/weather widget timing out from Homepage, separate from service cards.","- HTTP 200 for the portal is not sufficient for UI closure when Homepage logs still contain API errors." -RELATED_CLUSTER_RESOURCES=[{"vmid":160,"node":"pve02","status":"running","name_sha256":"6c602e84ee97babcf326574bff0e2841d9cacf16d14205d22333adf20ccc31d4"},{"vmid":210,"node":"pve01","status":"running","name_sha256":"61da6e04392026041610b476d6b0f1772cc199a94154dadc9dea8150655eced0"},{"vmid":211,"node":"pve03","status":"running","name_sha256":"b2c494a42ab7082a3d4f8184465b9bb4d43c58a397c70e048c49a548c3af139a"}] -CLUSTER_BACKUP_JOB_COUNT=0 -CLUSTER_BACKUP_JOBS_SANITIZED=[] -GUEST_QGA_TRANSPORT_RC=0 -GUEST_EXITCODE=0 -TRANSPORT_STDERR_SHA256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -GUEST_CONTINUATION_OUTPUT_BEGIN -XF_SHA=d0c10d91d743e0a541d9a1b201080491dae0a8b1757866f113ef707b83403219 -SERVER_PHP_LINT_RC=0 -SERVER_PHP_LINT_STDERR_SHA256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -PHP_AUDIT_RC=0 -PHP_AUDIT_STDERR_SHA256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -PHP_AUDIT_STDERR_BYTES=0 -PHP_AUDIT_OUTPUT_BEGIN -ADDON_COUNT=1 -ADDONS=[{"addon_id":"XF","title":"XenForo","version_string":"2.3.12","active":1}] -SUPPORT_ADDON_MATCHES=[] -XF_ROUTE_COLUMNS=["route_id","route_type","route_prefix","sub_name","format","build_class","build_method","controller","context","action_prefix","addon_id"] -SUPPORT_ROUTES=[] -EMAIL_TRANSPORT_TYPE=array -EMAIL_TRANSPORT_CLASS= -EMAIL_TRANSPORT_OPTION_KEYS=["emailTransport"] -DEFAULT_EMAIL_NONEMPTY=true -CONTACT_EMAIL_NONEMPTY=true -OPTION_boardUrl_PRESENT=true -OPTION_boardUrl_NONEMPTY=true -OPTION_defaultLanguageId_PRESENT=true -OPTION_defaultLanguageId_NONEMPTY=true -OPTION_defaultLanguageId_VALUE=1 -OPTION_defaultStyleId_PRESENT=true -OPTION_defaultStyleId_NONEMPTY=true -OPTION_defaultStyleId_VALUE=1 -OPTION_friendlyUrls_PRESENT=false -OPTION_friendlyUrls_NONEMPTY=false -OPTION_indexRoute_PRESENT=true -OPTION_indexRoute_NONEMPTY=true -OPTION_indexRoute_VALUE=forums/ -XF_ERROR_COUNT=16 -MANUAL_JOB_COUNT=0 -PERMISSION_REBUILD_JOB_COUNT=0 -REGISTRATION_ENABLED=false -NO_MUTATION=true -PHP_AUDIT_OUTPUT_END -EXEC_a2698bd30ec6_EXISTS=false -EXEC_e68e10a6e0ef_EXISTS=false -EXEC_620e1c7c6b42_EXISTS=false -MSMTPRC_EXISTS=false -ROOTFILE_76c10b8a6163_EXISTS=false -ROOTFILE_72b7466a08b5_EXISTS=false -ROOTFILE_cc3c8901c551_EXISTS=false -NO_MUTATION=true -GUEST_CONTINUATION_OUTPUT_END -PUBLIC_CONTINUATION_SURFACE={"SUPPORT_STAFF":"404|text/html; charset=utf-8|23063","FAVICON":"404|unknown/unknown; charset=utf-8|0","ROBOTS":"404|unknown/unknown; charset=utf-8|0","SITEMAP":"404|text/plain; charset=utf-8|10"} -BASELINE_CONTINUATION_CLEAN=true -RCA_719_SQL_FIELD_CAUSE=xf_addon uses addon_id; 719 queried add_on_id -TASK_COMPLETE=true -TASK_RESULT=PASS_PVEPRO_V1_BASELINE_CONTINUATION -NO_MUTATION=true -HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-260920-PVEPRO-V1-BASELINE-CONTINUATION-READONLY-720R1","status":"OK","changes_made":false,"rollback_started":false,"rollback_restored":null} +NEWFI191_AUTH={"command_id":"NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191","decision":"HOLD_USA_NETBIRD_FORWARDED_AGENT_TELEGRAM_EGRESS","error_code":"SSH_AUTH_DENIED","forwarded_agent":{"fingerprints":["SHA256:JMCyBDSD7PKqwwKndzDGAO4Lgm55nEmec9Ssn6QGtKg","SHA256:tfEP9WF58ZcGe5zL/juscxX/sVAeS6fxwwiPjpj2I5U","SHA256:PS+jG8Qun3vviOwZ4A2/ozwro+Jeav/x9VkfvH/d2yI"],"present":true,"ssh_add_rc":0},"hostkey":{"expected_match":true,"fingerprints":["SHA256:J/5Kp48TdNA/RdlTFGEX4nr71yM6uc5ub5Iahr4xAWE","SHA256:nen1KYo/PIGw45nlakIZpa/SSo/llm3tokCz0hFzboE","SHA256:DXJGwunC5tEVvnC3nRxyayTN8FXmyJcVgf+Oa6udQsY"]},"relay":{"connection_type":"P2P","name":"relay.netbird.selfhosted","netbird_ip_sha256":"0f61feb58699a097fdfae741ce53e84cd9eae29e8c8d893a0822f20af9231d4c","status":"Connected","usa_public_endpoint_confirmed":true},"ssh":{"accepted_fingerprints":[],"error_class":"AUTH_DENIED","offered_fingerprints":["SHA256:JMCyBDSD7PKqwwKndzDGAO4Lgm55nEmec9Ssn6QGtKg","SHA256:tfEP9WF58ZcGe5zL/juscxX/sVAeS6fxwwiPjpj2I5U","SHA256:PS+jG8Qun3vviOwZ4A2/ozwro+Jeav/x9VkfvH/d2yI"],"rc":255,"stderr_sha256":"96e972784f367ad113bee81e15345cf73d3a15b106f5857a98cfedf2074363a2","stdout_sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},"status":"FAIL","tcp22":true} +HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"NEWFI-260920-NEWFDOM-TELEGRAM214-NETBIRD-AUTH191","status":"FAIL","changes_made":false,"rollback_started":false,"rollback_restored":null} OUTPUT_END CHAT_OUTPUT_END