runtime: publish SUPPORT-261006-SNIKKET-HOME-ROLLBACK-PREFLIGHT-99740R1
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"channel": "homelab-runtime",
|
||||
"command_id": "SUPPORT-261006-SNIKKET-HOME-ROLLBACK-PREFLIGHT-99740R1",
|
||||
"status": "OK",
|
||||
"rc": 0,
|
||||
"host": "pve01",
|
||||
"mode": "read-only",
|
||||
"component": "snikket-home-rollback-preflight",
|
||||
"started_at_utc": "2026-10-06T18:02:31Z",
|
||||
"finished_at_utc": "2026-10-06T18:03:00Z",
|
||||
"reference_register_checked": true,
|
||||
"reference_sha256": "5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66",
|
||||
"error_register_checked": true,
|
||||
"error_register_sha256": "3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0",
|
||||
"command_sha256": "4336c13341dc97c6ef0a781e34aa07cfa6829de4686391dfbda4b3b00dc90150",
|
||||
"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": 0,
|
||||
"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": "4737052a112e41dfe5fe93073b59c14131211a94191d7ad6c2dd0dd76e8164c6",
|
||||
"sanitized_output_sha256": "4737052a112e41dfe5fe93073b59c14131211a94191d7ad6c2dd0dd76e8164c6",
|
||||
"output_truncated_in_json": false,
|
||||
"full_sanitized_output_url": "https://git.gram1.ru/.well-known/homelab-runtime/latest.txt",
|
||||
"output": "SNIKKET_HOME_ROLLBACK_PREFLIGHT=V1\nMODE=read-only\nNO_MUTATION=true\nSOURCE_HEAD=bd85699d8b588a34c480f10dee71323687bd48f1\nSOURCE_WORKTREE_DIRTY_COUNT=0\nSOURCE_ROLLBACK_NETWORK_PRESENT=true\nSOURCE_ROLLBACK_USES_CLOUDFLARE=true\nROLLBACK_STATE_PRESENT=true\nROLLBACK_STATE_SHA=b4696a99b8e13042680d3c56537e0e5e5b6d3e7fae69e01fb8b8f60d68c39fc7\nROLLBACK_STATE_MODE=600\nROLLBACK_STATE_MTIME=1786953752\nROLLBACK_STATE_JSON_VALID=true\nROLLBACK_STATE_HAS_DNS_CONTENT=true\nROLLBACK_STATE_HAS_DEFAULT_ROUTE=true\nROLLBACK_OLD_ROUTE_SHA=7c5515603e424ad8e85718ba716657be12298988ee11416f41081ec82e023409\nROLLBACK_HOME_IP_SHA=26ac437d63a8bcf254255cc970d7614e78bd0a67b97b5575a42a1c3ca7a301ee\nPVE01_IPIFY_RC=0\nPVE01_PUBLIC_IP_SHA=26ac437d63a8bcf254255cc970d7614e78bd0a67b97b5575a42a1c3ca7a301ee\nROLLBACK_HOME_MATCHES_CURRENT_PVE01_PUBLIC=true\nVM150_QGA_TRANSPORT_RC=0\nREC|VM150|QGA_EXIT=0\nREC|VM150|DOMAIN_SHA=04cb4a04e408d91abb9c63701ae969abf16d8a12b6f4f144c5edf2c28e03256b\nREC|VM150|EDGE_EGRESS_UNIT_PRESENT=true\nREC|VM150|EDGE_EGRESS_ACTIVE=active\nREC|VM150|EDGE_EGRESS_ENABLED=enabled\nREC|VM150|EDGE_EGRESS_UNIT_SHA=83a20356e221dfb22ea2a0d99e327f7c2f791a3d3127a46af2d1625b33c95b5d\nREC|VM150|OLDGW_SHA=4f9da1283166a1e9f4e6bc7dd240c76aef85772177f717f92abb6e8e2bb8de90\nREC|VM150|NEWGW_SHA=bc517b4af3298846906234d3d697d3820b0b652ade1880c937c9d71cd802c834\nREC|VM150|OLDGW_PING_RC=1\nREC|VM150|CURRENT_GW_SHA=bc517b4af3298846906234d3d697d3820b0b652ade1880c937c9d71cd802c834\nREC|VM150|REC|CONTAINER|NAME=snikket|RUNNING=true|RESTARTS=0\nREC|VM150|REC|CONTAINER|NAME=snikket-proxy|RUNNING=true|RESTARTS=0\nREC|VM150|REC|CONTAINER|NAME=snikket-certs|RUNNING=true|RESTARTS=0\nREC|VM150|REC|CONTAINER|NAME=snikket-portal|RUNNING=true|RESTARTS=0\nREC|VM150|LOCAL_HTTPS_RC=0\nREC|VM150|LOCAL_HTTPS_CODE=302\nVM130_QGA_TRANSPORT_RC=0\nREC|VM130|QGA_EXIT=0\nREC|VM130|ROLE=VM130\nREC|VM130|WG_CONFIG_PRESENT=true\nREC|VM130|WG_BACKUP_PRESENT=true\nREC|VM130|WG_CONFIG_SHA=42b046d580b2ccd6af8f3573fba4882c71c92b2938f3fed8edf58258bbc89615\nREC|VM130|WG_BACKUP_SHA=9012ece867ad7efa1b2d07020c1cdfc9d3a63f86fde9117bdd7435eef29a9735\nREC|VM130|WG_BACKUP_MODE=600\nREC|VM130|PRIORITY101_COUNT=1\nREC|VM130|TABLE17777_DEFAULT_COUNT=1\nREC|VM130|WG_EDGE_ACTIVE=active\nCURRENT_AUTHORITATIVE_BEGET=true\nREC|DNS|ROLE=primary|A_COUNT=1|MATCH_ROLLBACK_HOME=true\nREC|DNS|ROLE=groups|A_COUNT=1|MATCH_ROLLBACK_HOME=true\nREC|DNS|ROLE=share|A_COUNT=1|MATCH_ROLLBACK_HOME=true\nBEGET_LOGIN_CANDIDATE_COUNT=0\nBEGET_PASSWORD_CANDIDATE_COUNT=0\nBEGET_CREDENTIALS_UNIQUE=false\nREC|HOME_TCP|PORT=443|OPEN=true|MSEC=1\nREC|HOME_TCP|PORT=5000|OPEN=true|MSEC=0\nREC|HOME_TCP|PORT=5222|OPEN=true|MSEC=0\nREC|HOME_TCP|PORT=5349|OPEN=false|ERR=TimeoutError\nROLLBACK_PREFLIGHT_READY=false\nDECISION=PASS_SNIKKET_HOME_ROLLBACK_PREFLIGHT\nNEXT_GATE=ROLLBACK_PREFLIGHT_BLOCKER_REPAIR\nTASK_RESULT=SNIKKET_HOME_ROLLBACK_PREFLIGHT\nCHANGES_MADE=false\nROLLBACK_STARTED=false\nROLLBACK_RESTORED=null\nMUTATION_OUTCOME=NO_MUTATION\nHOMELAB_RESULT_CONTRACT={\"version\":1,\"command_id\":\"SUPPORT-261006-SNIKKET-HOME-ROLLBACK-PREFLIGHT-99740R1\",\"status\":\"OK\",\"changes_made\":false,\"rollback_started\":false,\"rollback_restored\":null}\n"
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
CHAT_OUTPUT_BEGIN
|
||||
COMMAND_ID=SUPPORT-261006-SNIKKET-HOME-ROLLBACK-PREFLIGHT-99740R1
|
||||
STATUS=OK
|
||||
RC=0
|
||||
HOST=pve01
|
||||
MODE=read-only
|
||||
COMPONENT=snikket-home-rollback-preflight
|
||||
REFERENCE_REGISTER_CHECK=OK
|
||||
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
|
||||
ERROR_REGISTER_CHECK=OK
|
||||
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
|
||||
COMMAND_SHA256=4336c13341dc97c6ef0a781e34aa07cfa6829de4686391dfbda4b3b00dc90150
|
||||
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
|
||||
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=4737052a112e41dfe5fe93073b59c14131211a94191d7ad6c2dd0dd76e8164c6
|
||||
SANITIZED_OUTPUT_SHA256=4737052a112e41dfe5fe93073b59c14131211a94191d7ad6c2dd0dd76e8164c6
|
||||
OUTPUT_BEGIN
|
||||
SNIKKET_HOME_ROLLBACK_PREFLIGHT=V1
|
||||
MODE=read-only
|
||||
NO_MUTATION=true
|
||||
SOURCE_HEAD=bd85699d8b588a34c480f10dee71323687bd48f1
|
||||
SOURCE_WORKTREE_DIRTY_COUNT=0
|
||||
SOURCE_ROLLBACK_NETWORK_PRESENT=true
|
||||
SOURCE_ROLLBACK_USES_CLOUDFLARE=true
|
||||
ROLLBACK_STATE_PRESENT=true
|
||||
ROLLBACK_STATE_SHA=b4696a99b8e13042680d3c56537e0e5e5b6d3e7fae69e01fb8b8f60d68c39fc7
|
||||
ROLLBACK_STATE_MODE=600
|
||||
ROLLBACK_STATE_MTIME=1786953752
|
||||
ROLLBACK_STATE_JSON_VALID=true
|
||||
ROLLBACK_STATE_HAS_DNS_CONTENT=true
|
||||
ROLLBACK_STATE_HAS_DEFAULT_ROUTE=true
|
||||
ROLLBACK_OLD_ROUTE_SHA=7c5515603e424ad8e85718ba716657be12298988ee11416f41081ec82e023409
|
||||
ROLLBACK_HOME_IP_SHA=26ac437d63a8bcf254255cc970d7614e78bd0a67b97b5575a42a1c3ca7a301ee
|
||||
PVE01_IPIFY_RC=0
|
||||
PVE01_PUBLIC_IP_SHA=26ac437d63a8bcf254255cc970d7614e78bd0a67b97b5575a42a1c3ca7a301ee
|
||||
ROLLBACK_HOME_MATCHES_CURRENT_PVE01_PUBLIC=true
|
||||
VM150_QGA_TRANSPORT_RC=0
|
||||
REC|VM150|QGA_EXIT=0
|
||||
REC|VM150|DOMAIN_SHA=04cb4a04e408d91abb9c63701ae969abf16d8a12b6f4f144c5edf2c28e03256b
|
||||
REC|VM150|EDGE_EGRESS_UNIT_PRESENT=true
|
||||
REC|VM150|EDGE_EGRESS_ACTIVE=active
|
||||
REC|VM150|EDGE_EGRESS_ENABLED=enabled
|
||||
REC|VM150|EDGE_EGRESS_UNIT_SHA=83a20356e221dfb22ea2a0d99e327f7c2f791a3d3127a46af2d1625b33c95b5d
|
||||
REC|VM150|OLDGW_SHA=4f9da1283166a1e9f4e6bc7dd240c76aef85772177f717f92abb6e8e2bb8de90
|
||||
REC|VM150|NEWGW_SHA=bc517b4af3298846906234d3d697d3820b0b652ade1880c937c9d71cd802c834
|
||||
REC|VM150|OLDGW_PING_RC=1
|
||||
REC|VM150|CURRENT_GW_SHA=bc517b4af3298846906234d3d697d3820b0b652ade1880c937c9d71cd802c834
|
||||
REC|VM150|REC|CONTAINER|NAME=snikket|RUNNING=true|RESTARTS=0
|
||||
REC|VM150|REC|CONTAINER|NAME=snikket-proxy|RUNNING=true|RESTARTS=0
|
||||
REC|VM150|REC|CONTAINER|NAME=snikket-certs|RUNNING=true|RESTARTS=0
|
||||
REC|VM150|REC|CONTAINER|NAME=snikket-portal|RUNNING=true|RESTARTS=0
|
||||
REC|VM150|LOCAL_HTTPS_RC=0
|
||||
REC|VM150|LOCAL_HTTPS_CODE=302
|
||||
VM130_QGA_TRANSPORT_RC=0
|
||||
REC|VM130|QGA_EXIT=0
|
||||
REC|VM130|ROLE=VM130
|
||||
REC|VM130|WG_CONFIG_PRESENT=true
|
||||
REC|VM130|WG_BACKUP_PRESENT=true
|
||||
REC|VM130|WG_CONFIG_SHA=42b046d580b2ccd6af8f3573fba4882c71c92b2938f3fed8edf58258bbc89615
|
||||
REC|VM130|WG_BACKUP_SHA=9012ece867ad7efa1b2d07020c1cdfc9d3a63f86fde9117bdd7435eef29a9735
|
||||
REC|VM130|WG_BACKUP_MODE=600
|
||||
REC|VM130|PRIORITY101_COUNT=1
|
||||
REC|VM130|TABLE17777_DEFAULT_COUNT=1
|
||||
REC|VM130|WG_EDGE_ACTIVE=active
|
||||
CURRENT_AUTHORITATIVE_BEGET=true
|
||||
REC|DNS|ROLE=primary|A_COUNT=1|MATCH_ROLLBACK_HOME=true
|
||||
REC|DNS|ROLE=groups|A_COUNT=1|MATCH_ROLLBACK_HOME=true
|
||||
REC|DNS|ROLE=share|A_COUNT=1|MATCH_ROLLBACK_HOME=true
|
||||
BEGET_LOGIN_CANDIDATE_COUNT=0
|
||||
BEGET_PASSWORD_CANDIDATE_COUNT=0
|
||||
BEGET_CREDENTIALS_UNIQUE=false
|
||||
REC|HOME_TCP|PORT=443|OPEN=true|MSEC=1
|
||||
REC|HOME_TCP|PORT=5000|OPEN=true|MSEC=0
|
||||
REC|HOME_TCP|PORT=5222|OPEN=true|MSEC=0
|
||||
REC|HOME_TCP|PORT=5349|OPEN=false|ERR=TimeoutError
|
||||
ROLLBACK_PREFLIGHT_READY=false
|
||||
DECISION=PASS_SNIKKET_HOME_ROLLBACK_PREFLIGHT
|
||||
NEXT_GATE=ROLLBACK_PREFLIGHT_BLOCKER_REPAIR
|
||||
TASK_RESULT=SNIKKET_HOME_ROLLBACK_PREFLIGHT
|
||||
CHANGES_MADE=false
|
||||
ROLLBACK_STARTED=false
|
||||
ROLLBACK_RESTORED=null
|
||||
MUTATION_OUTCOME=NO_MUTATION
|
||||
HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-261006-SNIKKET-HOME-ROLLBACK-PREFLIGHT-99740R1","status":"OK","changes_made":false,"rollback_started":false,"rollback_restored":null}
|
||||
|
||||
OUTPUT_END
|
||||
CHAT_OUTPUT_END
|
||||
+8
-8
File diff suppressed because one or more lines are too long
+64
-403
@@ -1,15 +1,15 @@
|
||||
CHAT_OUTPUT_BEGIN
|
||||
COMMAND_ID=SUPPORT-261006-SNIKKET-WGEDGE-DESIGN-STATE-RCA-99739R1
|
||||
COMMAND_ID=SUPPORT-261006-SNIKKET-HOME-ROLLBACK-PREFLIGHT-99740R1
|
||||
STATUS=OK
|
||||
RC=0
|
||||
HOST=pve01
|
||||
MODE=read-only
|
||||
COMPONENT=snikket-wgedge-design-state-rca
|
||||
COMPONENT=snikket-home-rollback-preflight
|
||||
REFERENCE_REGISTER_CHECK=OK
|
||||
REFERENCE_SHA256=5a3d8e5154c41cb582a4e0aca68090be1f0138918bf82131a948df326f9d8d66
|
||||
ERROR_REGISTER_CHECK=OK
|
||||
ERROR_REGISTER_SHA256=3b09a553ec0f527ed3afeed4753f52a74ee3036045bbfb3c685e9f8af4ba7ba0
|
||||
COMMAND_SHA256=a60a8c29d502a49e98c500b961f57451d0ca3fd661de694738452d4ba50dff96
|
||||
COMMAND_SHA256=4336c13341dc97c6ef0a781e34aa07cfa6829de4686391dfbda4b3b00dc90150
|
||||
DUPLICATE_FAILED_COMMAND_BLOCKED=false
|
||||
EXECUTION_STARTED=true
|
||||
CHANGE_DECLARED=false
|
||||
@@ -24,415 +24,76 @@ MUTATION_OUTCOME=NO_MUTATION
|
||||
SANITIZED=yes
|
||||
SECRETS_INCLUDED=no
|
||||
PRIVATE_ADDRESSES_INCLUDED=no
|
||||
RAW_EVIDENCE_SHA256=64709396903adcb76579d798fddab1c280c55806f26dc184c45423275962c07d
|
||||
SANITIZED_OUTPUT_SHA256=64709396903adcb76579d798fddab1c280c55806f26dc184c45423275962c07d
|
||||
RAW_EVIDENCE_SHA256=4737052a112e41dfe5fe93073b59c14131211a94191d7ad6c2dd0dd76e8164c6
|
||||
SANITIZED_OUTPUT_SHA256=4737052a112e41dfe5fe93073b59c14131211a94191d7ad6c2dd0dd76e8164c6
|
||||
OUTPUT_BEGIN
|
||||
SNIKKET_WGEDGE_DESIGN_STATE_RCA=V1
|
||||
SNIKKET_HOME_ROLLBACK_PREFLIGHT=V1
|
||||
MODE=read-only
|
||||
NO_MUTATION=true
|
||||
SOURCE_REPO_BASENAME=homelab-ops
|
||||
SOURCE_HEAD=bd85699d8b588a34c480f10dee71323687bd48f1
|
||||
SOURCE_BRANCH=main
|
||||
SOURCE_WORKTREE_DIRTY_COUNT=0
|
||||
REC|COMMIT|LABEL=ORIGIN|PRESENT=true|COMMIT=911d8cc52d5e8a677f132b736d01ade7a5879e59|DATE=2026-08-17T10:27:24+03:00|SUBJECT=CR-2026-0080: build Snikket EDGE cutover task|PARENTS=bcee02410290c4563fea4507a35fdf6dce08d674
|
||||
REC|COMMIT_FILES|LABEL=ORIGIN|COUNT=17
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=task-package.sha256|PARENT=CR-2026-0080|PATH_SHA=070b91ffb62312169dc9f08e768758b846237b4c56e71cc58e5946da174dafc1
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=2026-08-17-snikket-edge-cutover.md|PARENT=plans|PATH_SHA=72bcfe0160d221fc3f06466006c3163dc2e5f67f2224cacd1c5c50e02135eb37
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=1|# Snikket EDGE Cutover Implementation Plan
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=3|**Goal:** finish the traffic cutover of chat.gram1.ru to EDGE-01 while preserving rollback and keeping VM150 source-policy disabled until DNS convergence.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=5|## Task 1 — Version the production package
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=6|- Create `tasks/snikket-edge-cutover-v1/task.json` with schema 2, controlled_apply, fail_fast, seven phases, exact expected outputs and rollback contract.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=7|- Create executable phase wrappers: `phases/preflight.sh`, `prepare.sh`, `dry-run.sh`, `apply.sh`, `verify.sh`, `rollback.sh`, `seal.sh`.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=8|- Create `tools/cutover.py` as the single orchestration implementation; wrappers only select the phase.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=9|- Create `assets/edge01-public-ingress.nft` that removes only the temporary source restriction while retaining transitional symmetric SNAT.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=10|- Create `assets/edge01-home-restricted-ingress.nft` as the exact operator rollback contract.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=14|- Create `tests/test_cr_2026_0080_snikket_edge_cutover.py` before implementation.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=15|- RED assertions: task package absent; public ingress must not contain `ip saddr IP_REDACTED`; source-policy activation must be gated after DNS convergence; seven phase files must exist and be executable; rollback must restore old A and routing state.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=20|- preflight: prove chat A is still IP_REDACTED, persistent ingress canary is green, edge-vm table 17777 exists, VM150 policy rule is absent, VM150 network renderer has the expected old gateway, and NPMplus can perform a non-mutating Cloudflare record lookup.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=21|- prepare: capture exact non-sensitive DNS metadata, edge-vm routing configuration and VM150 network-file bytes into the run rollback directory.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=22|- dry-run: calculate the exact A-record mutation, policy rule, VM150 gateway change and rollback operations without production mutation.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=23|- apply: require explicit EDGE-01 public-ingress operator attestation; change only chat.gram1.ru A to IP_REDACTED; wait for authoritative and public convergence; only then install priority-101 source policy for IP_REDACTED via table 17777 and change VM150 gateway to IP_REDACTED; refresh only the Snikket server container if effective TURN addressing still shows the old origin.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=24|- verify: HTTPS, TCP 5000/5222/3478/3479/5349/5350, XMPP STARTTLS, TURN TLS, UDP STUN, VM150 outbound public IP IP_REDACTED, DNS convergence and effective TURN address without IP_REDACTED.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=25|- rollback: restore VM150 network bytes and live default route, remove priority-101 policy and persistence, restore the previous chat A value; operator applies the versioned EDGE-01 restricted-ingress rollback asset if EDGE ingress must also be reverted.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=26|- seal: record only the proven traffic cutover. Do not remove turn.gram1.ru, rotate TURN auth material, alter certificate renewal or remove home-router forwards.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover.md|LINE=31|- On `root@edge01`, apply the merged public-ingress asset with host guard, backup, `nft -c`, live canary and rollback.
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=2026-08-17-snikket-edge-cutover-design.md|PARENT=specs|PATH_SHA=224ed8ac7b09df73545e49a1ac681848f67b00df285ec5a3b7b8398f21d015ee
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover-design.md|LINE=1|# Snikket EDGE Traffic Cutover Design
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover-design.md|LINE=7|Move chat.gram1.ru from home IP IP_REDACTED to EDGE-01 IP_REDACTED. Persistent EDGE-01 and edge-vm inbound transit is already installed and TCP, XMPP STARTTLS, TURN TLS, UDP STUN and HTTPS canaries pass.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover-design.md|LINE=8|Before cutover, EDGE-01 ingress is still restricted to source IP_REDACTED, chat.gram1.ru A is still IP_REDACTED, edge-vm table 17777 is ready, and no source rule for VM150 IP_REDACTED is active.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover-design.md|LINE=11|CR0080 covers only production traffic cutover: publicize the verified EDGE-01 ingress contract, change only chat.gram1.ru A to IP_REDACTED, wait for DNS convergence, activate VM150 egress through edge-vm and EDGE-01, refresh effective TURN addressing, verify, rollback and seal.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover-design.md|LINE=12|Excluded post-cutover work: remove turn.gram1.ru, rotate the TURN static auth se=REDACTED
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover-design.md|LINE=15|Use tasks/snikket-edge-cutover-v1 on pve01.gram1.ru with controlled_apply and phases preflight, prepare, dry-run, apply, verify, rollback and seal.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover-design.md|LINE=16|EDGE-01 remains manual-operator access only. CR0080 versions the exact public-ingress contract, but the operator applies it from the established root@edge01 session; the pve01 task must not invent an automated EDGE-01 SSH path.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover-design.md|LINE=17|DNS mutation is fail-closed: apply requires operator attestation that the exact EDGE-01 public-ingress contract is active and an approved local DNS credential file path. Credential values are never printed.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover-design.md|LINE=20|Apply order is fixed: prove pre-state; require EDGE-01 public-ingress attestation and canary; change chat A; wait for authoritative and public DNS convergence; only then activate edge-vm source policy for IP_REDACTED via table 17777 and move VM150 Internet traffic through IP_REDACTED; refresh only the required Snikket or coturn component.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover-design.md|LINE=21|Verification covers HTTPS chat/groups/share; TCP 5000,5222,3478,3479,5349,5350; XMPP STARTTLS; TURN TLS; UDP STUN and relay 60000-60199; VM150 outbound IP IP_REDACTED; DNS convergence; and no effective TURN advertisement containing IP_REDACTED.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover-design.md|LINE=23|## Failure and rollback
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover-design.md|LINE=24|Every phase is fail-fast and no later phase runs after a failed gate. Prepare re=REDACTED
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:2026-08-17-snikket-edge-cutover-design.md|LINE=25|Zero-secret diagnostics are mandatory: never print passwords, API credentials, p=REDACTED
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=README.txt|PARENT=snikket-edge-cutover-v1|PATH_SHA=418b863db2e962e7c0bf3a5540f0f4b9a328c01120ffd81371c9cdf43a8664df
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:README.txt|LINE=1|snikket-edge-cutover-v1
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:README.txt|LINE=4|- production traffic cutover for chat.gram1.ru from IP_REDACTED to EDGE-01 IP_REDACTED;
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:README.txt|LINE=5|- DNS convergence before VM150 source-policy activation;
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:README.txt|LINE=6|- rollback-safe edge-vm and VM150 routing transition;
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:README.txt|LINE=7|- no automated EDGE-01 access from pve01.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:README.txt|LINE=9|Manual EDGE-01 gate:
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:README.txt|LINE=10|1. Apply assets/edge01-public-ingress.nft from the established root@edge01 MobaXterm session.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:README.txt|LINE=11|2. Verify nft -c and full public service canary.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:README.txt|LINE=12|3. Supply HOMELAB_SNIKKET_EDGE01_PUBLIC_INGRESS_ATTEST_SHA256 equal to the merged asset SHA256 when running apply.
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:README.txt|LINE=17|turn.gram1.ru cleanup, TURN secret rotation, certificate renewal changes, home-r=REDACTED
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=edge01-home-restricted-ingress.nft|PARENT=assets|PATH_SHA=ae3180f52ef9fecc84167c6f8618aa48a669c99f5387914f04f96b3ae4bff345
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:edge01-home-restricted-ingress.nft|LINE=1|add chain inet edge01_filter snikket_prod_ingress
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:edge01-home-restricted-ingress.nft|LINE=2|add rule inet edge01_filter snikket_prod_ingress iifname "eth0" oifname "wg-home" ip saddr IP_REDACTED ip daddr IP_REDACTED tcp dport { 3478, 3479, 5000, 5222, 5269, 5349, 5350 } accept
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:edge01-home-restricted-ingress.nft|LINE=3|add rule inet edge01_filter snikket_prod_ingress iifname "eth0" oifname "wg-home" ip saddr IP_REDACTED ip daddr IP_REDACTED udp dport { 3478-3479, 5349-5350, 60000-60199 } accept
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:edge01-home-restricted-ingress.nft|LINE=4|add rule inet edge01_filter snikket_prod_ingress iifname "wg-home" oifname "eth0" ip saddr IP_REDACTED ip daddr IP_REDACTED ct state established,related accept
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:edge01-home-restricted-ingress.nft|LINE=5|insert rule inet edge01_filter forward jump snikket_prod_ingress comment "SNIKKET_PROD_INGRESS_JUMP"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:edge01-home-restricted-ingress.nft|LINE=7|table ip snikket_prod_ingress {
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=edge01-public-ingress.nft|PARENT=assets|PATH_SHA=1678d03b6d6be773e5c875c7f85a548c0bd95314c58645ed8f567df9e8aaacfd
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:edge01-public-ingress.nft|LINE=1|add chain inet edge01_filter snikket_prod_ingress
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:edge01-public-ingress.nft|LINE=2|add rule inet edge01_filter snikket_prod_ingress iifname "eth0" oifname "wg-home" ip daddr IP_REDACTED tcp dport { 3478, 3479, 5000, 5222, 5349, 5350 } accept
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:edge01-public-ingress.nft|LINE=3|add rule inet edge01_filter snikket_prod_ingress iifname "eth0" oifname "wg-home" ip daddr IP_REDACTED udp dport { 3478-3479, 5349-5350, 60000-60199 } accept
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:edge01-public-ingress.nft|LINE=4|add rule inet edge01_filter snikket_prod_ingress iifname "wg-home" oifname "eth0" ip saddr IP_REDACTED ct state established,related accept
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:edge01-public-ingress.nft|LINE=5|insert rule inet edge01_filter forward jump snikket_prod_ingress comment "SNIKKET_PROD_INGRESS_JUMP"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:edge01-public-ingress.nft|LINE=7|table ip snikket_prod_ingress {
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=npmplus-cloudflare-a.sh|PARENT=assets|PATH_SHA=48c7bcfaa5f7de8282caa4b35cabc573876f7c8336c5988c3029b66c074fd1f4
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=apply.sh|PARENT=phases|PATH_SHA=c375ac75c7c4370efdd0c29fce9f5afc7a46ac38e10bf4e031d2fdeb44525324
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:apply.sh|LINE=10|python3 "$TASK_DIR/tools/cutover.py" apply
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=dry-run.sh|PARENT=phases|PATH_SHA=a1bf65bfca5d89a9e6f37e7ef1e95d23300b884df043c9e68fae1dd95944482d
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:dry-run.sh|LINE=10|python3 "$TASK_DIR/tools/cutover.py" dry-run
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=preflight.sh|PARENT=phases|PATH_SHA=cd56fdeeae17cfc3be7d68b996f8b5350ccd930252c88da7871bbbe7f97a0def
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:preflight.sh|LINE=10|python3 "$TASK_DIR/tools/cutover.py" preflight
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=prepare.sh|PARENT=phases|PATH_SHA=f4c8867f85674ee74bc7f04a82b8336eeeefaa959ec9b198ca460170de1e1990
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:prepare.sh|LINE=10|python3 "$TASK_DIR/tools/cutover.py" prepare
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=rollback.sh|PARENT=phases|PATH_SHA=f2998ffe82d9ff129223379159c31aaa5bd5f4769b2489b3c8d471b7d21d7064
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:rollback.sh|LINE=5| printf 'ROOT_CAUSE_COUNT=1\nFAILED_PHASE=rollback\n' >&2
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:rollback.sh|LINE=10|python3 "$TASK_DIR/tools/cutover.py" rollback
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=seal.sh|PARENT=phases|PATH_SHA=49326c4de4695fa8d0fb4ae205ba863305f1234c60308c011ce7f1cb87afdea2
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:seal.sh|LINE=10|python3 "$TASK_DIR/tools/cutover.py" seal
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=verify.sh|PARENT=phases|PATH_SHA=e562fbaefd2c1e7f70ef0cdbb832e4a09472614da0c6824eac57f8267df00c74
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:verify.sh|LINE=10|python3 "$TASK_DIR/tools/cutover.py" verify
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=task.json|PARENT=snikket-edge-cutover-v1|PATH_SHA=9a63e2769a24f3ce2c23c172837f46c1f044cbd8f886e45313a3b0e7e467e55d
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=3| "task_id": "snikket-edge-cutover-v1",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=6| "production_change": true,
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=14| "rollback": "phases/rollback.sh",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=18| "active_backup_restore_max": 0
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=22| "EDGE-01 public service path at IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=23| "edge-vm IP_REDACTED routing and /etc/wireguard/wg-edge01.conf metadata",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=24| "VM150 QGA network and Snikket runtime state",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=33| "$HOMELAB_RUN_DIR/rollback.json",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=35| "/mnt/staging/homelab-admin-rollback/snikket-edge-cutover-v1/state.json",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=37| "edge-vm policy rule priority 101 and wg-edge01.conf PostUp/PostDown",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=38| "VM150 /etc/systemd/system/snikket-edge-egress.service"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=42| "edge-vm policy routing for source IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=43| "VM150 default Internet route via IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=44| "Snikket server container restart after DNS convergence"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=47| "EDGE-01 is never accessed automatically by this task",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=48| "turn.gram1.ru is not modified or deleted",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=49| "TURN static auth material is not read, printed, or rotated",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=51| "home router forwards are unchanged",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=57| "tools/cutover.py"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=66| "verification": "pre-cutover DNS, public canary, edge-vm table 17777, absent VM150 source policy, VM150 old default route, non-mutating Cloudflare lookup"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=71| "verification": "non-secret rollback state is persisted before mutation"=REDACTED
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=76| "verification": "exact DNS/routing/service mutations and rollback order are calculated without mutation"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=81| "verification": "EDGE-01 public ingress attestation, DNS convergence, source policy, VM150 egress, Snikket refresh"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=86| "verification": "DNS, HTTPS, XMPP, TURN/STUN, VM150 egress and effective coturn external address"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=89| "path": "$HOMELAB_RUN_DIR/rollback.json",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=90| "producer": "phases/rollback.sh",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=91| "verification": "old DNS and pre-cutover edge-vm/VM150 routing are restored; EDGE-01 rollback remains manual"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=96| "verification": "traffic cutover is verified without post-cutover hardening changes"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=106| "host": "edge-vm IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=111| "host": "VM150",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=116| "host": "EDGE-01 IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=118| "compile": "versioned nft asset; nft -c; host guard; external canary"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=121| "rollback": {
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=122| "command": "HOMELAB_CONTROLLED_APPLY_CONFIRM=snikket-edge-cutover-v1 /opt/homelab-admin/bin/homelab-admin run TASK_DIR rollback",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=123| "verification": "restore old chat A, remove VM150 source policy and persistent egress service, restore old default route; manual EDGE-01 restricted-ingress asset remains available"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=130| "edge01_public_ip": "IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=131| "edge01_wg_ip": "IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=132| "edgevm_wg_ip": "IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=133| "edgevm_lan_ip": "IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=134| "vm150_ip": "IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=137| "policy_table": 17777,
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=139| "turn_udp_min": 60000,
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=140| "turn_udp_max": 60199,
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=141| "edge01_automated_access": false,
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=142| "turn_legacy_record_mutation": false,
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=143| "turn_secret_rotation": false,=REDACTED
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:task.json|LINE=145| "home_router_mutation": false,
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=cutover.py|PARENT=tools|PATH_SHA=d90388278e2775b1ac7534b35946dfa3dadd03f65cd16117db653731b47346ad
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=9|EDGE = "IP_REDACTED"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=10|EDGEVM = "IP_REDACTED"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=11|VM150 = "IP_REDACTED"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=13|WG_TABLE = "17777"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=14|RULE_PRIO = "101"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=15|ROLLBACK = pathlib.Path("/mnt/staging/homelab-admin-rollback/snikket-edge-cutover-v1")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=16|EDGE_SSH = ["ssh","-o","BatchMode=yes","-o","StrictHostKeyChecking=yes","-o","ConnectTimeout=8","debian@IP_REDACTED"]
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=19|class CutoverError(RuntimeError):
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=24| if check and p.returncode:
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=25| raise CutoverError(f"command-failed rc={p.returncode} tool={pathlib.Path(cmd[0]).name}")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=26| return p
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=31| raise CutoverError("HOMELAB_RUN_DIR missing")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=34| return p
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=41| raise CutoverError("qga-json") from e
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=43| raise CutoverError("qga-command-failed")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=44| return d.get("out-data","")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=46|def edgevm(script,timeout=90):
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=47| return sh(EDGE_SSH+["sudo","-n","bash","-s"],input_text=script,timeout=timeout).stdout
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=51| cmd=EDGE_SSH+["sudo","-n","docker","exec","-i","npmplus","sh","-s","--",action,CHAT]
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=58| raise CutoverError("cloudflare-safe-json") from e
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=60| raise CutoverError("cloudflare-operation-failed")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=61| return d
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=66| raise CutoverError("no-authoritative-ns")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=67| return out[0].rstrip(".")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=75| return out[-1] if out else ""
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=82| return last
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=84| raise CutoverError("dns-convergence-timeout:"+json.dumps(last,sort_keys=True))
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=97| raise CutoverError("tcp-canary")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=98| return out
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=109| raise CutoverError("wan-5269-must-remain-closed")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=110| return True
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=118| raise CutoverError("https-canary")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=119| return out
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=122| x=sh(["openssl","s_client","-connect",f"{EDGE}:5222","-starttls","xmpp","-xmpphost",CHAT,"-verify_return_error"],input_text="",check=False,timeout=15)
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=123| t=sh(["openssl","s_client","-connect",f"{EDGE}:5349","-servername",CHAT,"-verify_return_error"],input_text="",check=False,timeout=15)
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=124| if "Verify return code: 0 (ok)" not in x.stdout+x.stderr:
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=125| raise CutoverError("xmpp-tls")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=126| if "Verify return code: 0 (ok)" not in t.stdout+t.stderr:
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=127| raise CutoverError("turn-tls")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=128| return {"xmpp":True,"turn":True}
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=144| raise CutoverError("udp-stun")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=145| return out
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=148| return {"tcp":tcp_canary(EDGE),"https":https_canary(EDGE),"tls":tls_canary(),"stun":udp_stun(EDGE)}
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=150|def edgevm_rule_present():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=151| return bool(re.search(r"^101:\s+from 192\.168\.50\.31(?:/32)? lookup 17777$",edgevm("ip -4 rule show"),re.M))
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=153|def edgevm_priority_free():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=154| return not bool(re.search(r"^101:",edgevm("ip -4 rule show"),re.M))
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=156|def edgevm_table_ready():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=157| return "default dev wg-edge01" in edgevm("ip -4 route show table 17777")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=160| return qga("ip -4 route show default | head -n1").strip()
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=162|def vm_egress():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=163| return qga("curl -4 -fsS --connect-timeout 5 --max-time 12 https://api.ipify.org").strip()
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=165|def coturn_external():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=166| inner='pid="$(pgrep -xo turnserver || true)"; [ -n "$pid" ] || exit 2; tr "\\0" "\\n" <"/proc/$pid/cmdline" | grep -A1 -x -- "-X" | tail -n1'
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=167| return qga("docker exec snikket sh -lc "+json.dumps(inner)).strip()
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=171| raise CutoverError("chat-authoritative-a-not-home")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=172| if not edgevm_table_ready():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=173| raise CutoverError("table-17777-not-ready")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=174| if edgevm_rule_present():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=175| raise CutoverError("vm150-source-rule-already-present")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=176| if not edgevm_priority_free():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=177| raise CutoverError("policy-priority-101-in-use")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=180| raise CutoverError("vm150-default-not-home")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=183| raise CutoverError("cloudflare-record-prestate")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=184| return {"dns":rec,"default_route":d,"public_canary":public_canary()}
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=186|def save_rollback(state):
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=187| ROLLBACK.mkdir(parents=True,exist_ok=True); os.chmod(ROLLBACK,0o700)
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=188| p=ROLLBACK/"state.json"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=190| raise CutoverError("rollback-state-already-exists")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=193|def load_rollback():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=194| p=ROLLBACK/"state.json"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=196| raise CutoverError("rollback-state-missing")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=197| return json.loads(p.read_text())
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=199|def install_edgevm_policy():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=201|CFG=/etc/wireguard/wg-edge01.conf
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=202|BK=/root/wg-edge01.before-snikket-edge-cutover-v1.conf
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=208|up="PostUp = ip rule add priority 101 from IP_REDACTED lookup 17777"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=209|down="PostDown = ip rule del priority 101 from IP_REDACTED lookup 17777 2>/dev/null || true"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=211| marker="PostDown = ip route del table 17777 default dev wg-edge01 2>/dev/null || true"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=216|ip rule add priority 101 from IP_REDACTED lookup 17777
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=217|ip -4 rule show | grep -Eq '^101:.*from 192\.168\.50\.31(/32)? lookup 17777$'
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=219| edgevm(script)
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=221|def remove_edgevm_policy():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=222| edgevm('set -Eeuo pipefail; ip rule del priority 101 2>/dev/null || true; BK=/root/wg-edge01.before-snikket-edge-cutover-v1.conf; CFG=/etc/wireguard/wg-edge01.conf; if [ -f "$BK" ]; then cp -a "$BK" "$CFG"; fi')
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=225|Description=Snikket Internet egress via edge-vm
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=231|ExecStart=/usr/sbin/ip route replace default via IP_REDACTED dev eth0
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=232|ExecStop=/usr/sbin/ip route replace default via IP_REDACTED dev eth0
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=239|def install_vm_egress():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=241| qga(f'set -Eeuo pipefail; test ! -e /etc/systemd/system/snikket-edge-egress.service; printf %s {b64} | base64 -d >/etc/systemd/system/snikket-edge-egress.service; chmod 0644 /etc/systemd/system/snikket-edge-egress.service; systemctl daemon-reload; systemctl enable --now snikket-edge-egress.service; ip -4 route show default | grep -F "default via IP_REDACTED dev eth0"')
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=243|def remove_vm_egress():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=244| qga('set -Eeuo pipefail; systemctl disable --now snikket-edge-egress.service 2>/dev/null || true; rm -f /etc/systemd/system/snikket-edge-egress.service; systemctl daemon-reload; ip route replace default via IP_REDACTED dev eth0')
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=246|def refresh_snikket():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=247| qga("docker restart snikket >/dev/null; for i in $(seq 1 30); do docker exec snikket pgrep -x turnserver >/dev/null 2>&1 && exit 0; sleep 2; done; exit 1",timeout=80)
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=250| dns=dns_converged(EDGE,60); can=public_canary(); federation_5269_closed(EDGE)
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=251| if not edgevm_rule_present():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=252| raise CutoverError("vm150-source-rule-missing")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=254| if f"default via {EDGEVM} " not in d:
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=255| raise CutoverError("vm150-default-not-edgevm")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=256| eg=vm_egress()
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=257| if eg != EDGE:
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=258| raise CutoverError("vm150-egress-ip")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=259| ext=coturn_external()
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=260| if EDGE not in ext or HOME in ext:
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=261| raise CutoverError("coturn-external-address")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=262| return {"dns":dns,"canary":can,"vm_default":d,"vm_egress":eg,"coturn_external":ext}
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=266| d["edge01_public_ingress_asset_sha256"]=hashlib.sha256((ASSETS/"edge01-public-ingress.nft").read_bytes()).hexdigest()
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=271| save_rollback(st)
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=272| write_phase("prepare",{"status":"OK","rollback_state":str(ROLLBACK/"state.json"),"old_dns_content":st["dns"]["content"],"old_default_route":st["default_route"]})
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=275| st=load_rollback()
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=277| raise CutoverError("rollback-old-dns-not-home")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=278| actions=["operator applies versioned EDGE-01 public-ingress asset",f"chat A {HOME} -> {EDGE}","wait authoritative + IP_REDACTED + IP_REDACTED convergence",f"edge-vm rule priority {RULE_PRIO} from {VM150}/32 lookup {WG_TABLE}",f"VM150 default route {OLD_GW} -> {EDGEVM}","restart snikket container to refresh coturn external address","full verification"]
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=279| write_phase("dry-run",{"status":"OK","actions":actions,"rollback":["restore VM150 route","remove edge-vm source rule/persistence",f"chat A -> {HOME}","operator may apply EDGE-01 restricted-ingress asset"]})
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=282| expected=hashlib.sha256((ASSETS/"edge01-public-ingress.nft").read_bytes()).hexdigest()
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=283| if os.environ.get("HOMELAB_SNIKKET_EDGE01_PUBLIC_INGRESS_ATTEST_SHA256") != expected:
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=284| raise CutoverError("edge01-public-ingress-attestation-missing-or-wrong")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=285| load_rollback(); public_canary(); federation_5269_closed(EDGE); cf("set",EDGE); dns=dns_converged(EDGE,360)
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=286| install_edgevm_policy(); install_vm_egress()
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=287| eg=vm_egress()
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=288| if eg != EDGE:
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=289| raise CutoverError("vm150-egress-after-cutover")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=290| refresh_snikket(); ext=coturn_external()
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=291| if EDGE not in ext or HOME in ext:
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=292| raise CutoverError("coturn-external-after-refresh")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=293| write_phase("apply",{"status":"OK","dns":dns,"vm150_egress":eg,"coturn_external":ext})
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=298|def phase_rollback():
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=299| st=load_rollback(); remove_vm_egress(); remove_edgevm_policy(); old=st["dns"]["content"]; cf("set",old); dns=dns_converged(old,360)
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=300| write_phase("rollback",{"status":"OK","dns":dns,"vm_default":vm_default(),"edge01_manual_asset":"assets/edge01-home-restricted-ingress.nft"})
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=304| write_phase("seal",{"status":"SEALED","traffic_cutover":True,"verified_utc":=REDACTED
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=306|PHASES={"preflight":phase_preflight,"prepare":phase_prepare,"dry-run":phase_dry_run,"apply":phase_apply,"verify":phase_verify,"rollback":phase_rollback,"seal":phase_seal}
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=309| raise SystemExit("usage: cutover.py PHASE")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=312| except CutoverError as e:
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:cutover.py|LINE=313| print(f"CUTOVER_ERROR={e}",file=sys.stderr); raise SystemExit(1)
|
||||
REC|COMMIT_FILE|LABEL=ORIGIN|BASENAME=test_cr_2026_0080_snikket_edge_cutover.py|PARENT=tests|PATH_SHA=4166d64d93a4f81a59f9cf85d667034d01aad54a3b75c3d4aa1858fcfe9797bd
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=3|TASK=ROOT/"tasks"/"snikket-edge-cutover-v1"
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=5|class CR0080CutoverTest(unittest.TestCase):
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=12| self.assertEqual(task["task_id"],"snikket-edge-cutover-v1")
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=13| self.assertTrue(task["production_change"])
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=16| self.assertEqual(set(task["phases"]),{"preflight","prepare","dry-run","apply","verify","rollback","seal"})
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=17| expected=[f"$HOMELAB_RUN_DIR/{name}.json" for name in ("preflight","prepare","dry-run","apply","verify","rollback","seal")]
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=28| def test_public_ingress_removes_only_home_source_guard(self):
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=29| pub=(TASK/"assets/edge01-public-ingress.nft").read_text()
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=30| rb=(TASK/"assets/edge01-home-restricted-ingress.nft").read_text()
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=33| for needle in ("IP_REDACTED","IP_REDACTED","snat to IP_REDACTED","60000-60199","SNIKKET_PROD_INGRESS_JUMP"):
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=38| def test_apply_is_dns_then_policy_then_vmroute(self):
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=39| src=(TASK/"tools/cutover.py").read_text()
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=41| self.assertIn("HOMELAB_SNIKKET_EDGE01_PUBLIC_INGRESS_ATTEST_SHA256",body)
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=42| self.assertIn("federation_5269_closed(EDGE)",body)
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=43| self.assertLess(body.index('cf("set",EDGE)'),body.index("dns_converged(EDGE"))
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=44| self.assertIn("edge01-public-ingress-attestation-missing-or-wrong",body)
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=45| self.assertLess(body.index("dns_converged(EDGE"),body.index("install_edgevm_policy()"))
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=46| self.assertLess(body.index("install_edgevm_policy()"),body.index("install_vm_egress()"))
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=47| self.assertLess(body.index("install_vm_egress()"),body.index("refresh_snikket()"))
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=49| def test_rollback_reverses_routing_before_dns(self):
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=50| src=(TASK/"tools/cutover.py").read_text()
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=51| body=src[src.index("def phase_rollback():"):src.index("def phase_seal():")]
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=52| self.assertLess(body.index("remove_vm_egress()"),body.index("remove_edgevm_policy()"))
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=53| self.assertLess(body.index("remove_edgevm_policy()"),body.index('cf("set",old)'))
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=54| self.assertIn("edge01-home-restricted-ingress.nft",body)
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=59| self.assertIn("turn.gram1.ru is not modified or deleted",joined)
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=60| self.assertIn("TURN static auth material is not read, printed, or rotated",joined)
|
||||
REC|SOURCE_TEXT|LABEL=ORIGIN:test_cr_2026_0080_snikket_edge_cutover.py|LINE=62| self.assertIn("home router forwards are unchanged",joined)
|
||||
REC|COMMIT|LABEL=RETIRE|PRESENT=true|COMMIT=73c4cb4cc446ec8a10f81ba635624f2bf9373467|DATE=2026-08-31T22:01:03+03:00|SUBJECT=CR0104 add edge ingress retirement|PARENTS=53934522eaae9882f6c835e36b51a3b2162ec382
|
||||
REC|COMMIT_FILES|LABEL=RETIRE|COUNT=3
|
||||
REC|COMMIT_FILE|LABEL=RETIRE|BASENAME=edge-retire.sh|PARENT=homelab-command-stack-retirement|PATH_SHA=c9764b4b5fc86c1c3f92d9c26a0912de947256337e686df9991a336bbec22074
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-retire.sh|LINE=5|REWRITE="$HERE/edge-rewrite.py"
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-retire.sh|LINE=7|EDGE="${HOMELAB_EDGE_HOST:HOST_REDACTED
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-retire.sh|LINE=8|SSH=(ssh -o BatchMode=yes -o ConnectTimeout=10 "$EDGE")
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-retire.sh|LINE=14|BACKUP_ROOT='/var/backups/homelab-command-stack-retirement'
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-retire.sh|LINE=17|BACKUP="$BACKUP_ROOT/$STAMP/edge"
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-retire.sh|LINE=58|rollback() {
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-retire.sh|LINE=71| echo 'EDGE_RETIRE_ROLLBACK=OK' >&2
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-retire.sh|LINE=73| echo 'EDGE_RETIRE_ROLLBACK=FAILED' >&2
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-retire.sh|LINE=80|trap rollback ERR
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-retire.sh|LINE=111| echo 'EDGE_RETIRE_CHECK=OK'
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-retire.sh|LINE=121|"${SCP[@]}" "$TMP/9.conf" "$EDGE:$RPROXY"
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-retire.sh|LINE=122|"${SCP[@]}" "$TMP/http.conf" "$EDGE:$RHTTP"
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-retire.sh|LINE=146|echo "EDGE_RETIRE_STATUS=OK BACKUP=$BACKUP"
|
||||
REC|COMMIT_FILE|LABEL=RETIRE|BASENAME=edge-rewrite.py|PARENT=homelab-command-stack-retirement|PATH_SHA=5d82cec197ad13cd81785224c92618441b52804db7e20d7ba2ff3c18805206d9
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-rewrite.py|LINE=26| return pos + 1
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-rewrite.py|LINE=32| return text.rfind("\n", 0, pos) + 1
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-rewrite.py|LINE=42| return pos
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-rewrite.py|LINE=59| return text[:start] + text[end:]
|
||||
REC|SOURCE_TEXT|LABEL=RETIRE:edge-rewrite.py|LINE=83| return result
|
||||
REC|COMMIT_FILE|LABEL=RETIRE|BASENAME=test_cr_2026_0104_command_stack_retirement.py|PARENT=tests|PATH_SHA=a1fdf025e885c9a1b1fd5ce5a36c6e2930f3c9ede718660ae9705c01a6cf328b
|
||||
REC|COMMIT|LABEL=ROLLBACK|PRESENT=true|COMMIT=3bc25b7abde3ef263d728549e92de5ec6dc4a027|DATE=2026-08-31T22:13:52+03:00|SUBJECT=CR0104 add explicit edge rollback|PARENTS=7d9d9a81d64a88b3d09b21b0980f92f33dd26b15
|
||||
REC|COMMIT_FILES|LABEL=ROLLBACK|COUNT=3
|
||||
REC|COMMIT_FILE|LABEL=ROLLBACK|BASENAME=edge-retire.sh|PARENT=homelab-command-stack-retirement|PATH_SHA=c9764b4b5fc86c1c3f92d9c26a0912de947256337e686df9991a336bbec22074
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-retire.sh|LINE=5|REWRITE="$HERE/edge-rewrite.py"
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-retire.sh|LINE=7|EDGE="${HOMELAB_EDGE_HOST:HOST_REDACTED
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-retire.sh|LINE=8|SSH=(ssh -o BatchMode=yes -o ConnectTimeout=10 "$EDGE")
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-retire.sh|LINE=14|BACKUP_ROOT='/var/backups/homelab-command-stack-retirement'
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-retire.sh|LINE=17|BACKUP="$BACKUP_ROOT/$STAMP/edge"
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-retire.sh|LINE=58|rollback() {
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-retire.sh|LINE=71| echo 'EDGE_RETIRE_ROLLBACK=OK' >&2
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-retire.sh|LINE=73| echo 'EDGE_RETIRE_ROLLBACK=FAILED' >&2
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-retire.sh|LINE=80|trap rollback ERR
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-retire.sh|LINE=111| echo 'EDGE_RETIRE_CHECK=OK'
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-retire.sh|LINE=120| sudo -n tee '$BACKUP_ROOT/last-edge-backup' >/dev/null
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-retire.sh|LINE=123|"${SCP[@]}" "$TMP/9.conf" "$EDGE:$RPROXY"
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-retire.sh|LINE=124|"${SCP[@]}" "$TMP/http.conf" "$EDGE:$RHTTP"
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-retire.sh|LINE=148|echo "EDGE_RETIRE_STATUS=OK BACKUP=$BACKUP"
|
||||
REC|COMMIT_FILE|LABEL=ROLLBACK|BASENAME=edge-rollback.sh|PARENT=homelab-command-stack-retirement|PATH_SHA=5d21efde6be6c7c450c4521a51f902c96f16e6a40ab8bcbf4eb710e947a06da7
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-rollback.sh|LINE=4|EDGE="${HOMELAB_EDGE_HOST:HOST_REDACTED
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-rollback.sh|LINE=5|SSH=(ssh -o BatchMode=yes -o ConnectTimeout=10 "$EDGE")
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-rollback.sh|LINE=9|BACKUP_ROOT='/var/backups/homelab-command-stack-retirement'
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-rollback.sh|LINE=10|POINTER="$BACKUP_ROOT/last-edge-backup"
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-rollback.sh|LINE=19| '$BACKUP_ROOT'/*/edge) ;;
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-rollback.sh|LINE=20| *) echo 'INVALID_EDGE_BACKUP_POINTER' >&2; exit 1 ;;
|
||||
REC|SOURCE_TEXT|LABEL=ROLLBACK:edge-rollback.sh|LINE=44| echo \"EDGE_ROLLBACK_STATUS=OK BACKUP=\$BACKUP\"
|
||||
REC|COMMIT_FILE|LABEL=ROLLBACK|BASENAME=test_cr_2026_0104_command_stack_retirement.py|PARENT=tests|PATH_SHA=a1fdf025e885c9a1b1fd5ce5a36c6e2930f3c9ede718660ae9705c01a6cf328b
|
||||
REC|COMMIT|LABEL=MERGE_RETIRE|PRESENT=false
|
||||
REC|CURRENT_FILE|BASENAME=task.json|PARENT=snikket-edge-cutover-v1|PATH_SHA=9a63e2769a24f3ce2c23c172837f46c1f044cbd8f886e45313a3b0e7e467e55d|SHA=9cad3f6291663d6e85a556882c8ed751eaaa61b816b9bae934032fb0677267fd
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=3| "task_id": "snikket-edge-cutover-v1",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=6| "production_change": true,
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=14| "rollback": "phases/rollback.sh",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=18| "active_backup_restore_max": 0
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=22| "EDGE-01 public service path at IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=23| "edge-vm IP_REDACTED routing and /etc/wireguard/wg-edge01.conf metadata",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=24| "VM150 QGA network and Snikket runtime state",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=33| "$HOMELAB_RUN_DIR/rollback.json",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=35| "/mnt/staging/homelab-admin-rollback/snikket-edge-cutover-v1/state.json",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=37| "edge-vm policy rule priority 101 and wg-edge01.conf PostUp/PostDown",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=38| "VM150 /etc/systemd/system/snikket-edge-egress.service"
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=42| "edge-vm policy routing for source IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=43| "VM150 default Internet route via IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=44| "Snikket server container restart after DNS convergence"
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=47| "EDGE-01 is never accessed automatically by this task",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=48| "turn.gram1.ru is not modified or deleted",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=49| "TURN static auth material is not read, printed, or rotated",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=51| "home router forwards are unchanged",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=57| "tools/cutover.py"
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=66| "verification": "pre-cutover DNS, public canary, edge-vm table 17777, absent VM150 source policy, VM150 old default route, non-mutating Cloudflare lookup"
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=71| "verification": "non-secret rollback state is persisted before mutation"=REDACTED
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=76| "verification": "exact DNS/routing/service mutations and rollback order are calculated without mutation"
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=81| "verification": "EDGE-01 public ingress attestation, DNS convergence, source policy, VM150 egress, Snikket refresh"
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=86| "verification": "DNS, HTTPS, XMPP, TURN/STUN, VM150 egress and effective coturn external address"
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=89| "path": "$HOMELAB_RUN_DIR/rollback.json",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=90| "producer": "phases/rollback.sh",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=91| "verification": "old DNS and pre-cutover edge-vm/VM150 routing are restored; EDGE-01 rollback remains manual"
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=96| "verification": "traffic cutover is verified without post-cutover hardening changes"
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=106| "host": "edge-vm IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=111| "host": "VM150",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=116| "host": "EDGE-01 IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=118| "compile": "versioned nft asset; nft -c; host guard; external canary"
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=121| "rollback": {
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=122| "command": "HOMELAB_CONTROLLED_APPLY_CONFIRM=snikket-edge-cutover-v1 /opt/homelab-admin/bin/homelab-admin run TASK_DIR rollback",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=123| "verification": "restore old chat A, remove VM150 source policy and persistent egress service, restore old default route; manual EDGE-01 restricted-ingress asset remains available"
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=130| "edge01_public_ip": "IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=131| "edge01_wg_ip": "IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=132| "edgevm_wg_ip": "IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=133| "edgevm_lan_ip": "IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=134| "vm150_ip": "IP_REDACTED",
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=137| "policy_table": 17777,
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=139| "turn_udp_min": 60000,
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=140| "turn_udp_max": 60199,
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=141| "edge01_automated_access": false,
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=142| "turn_legacy_record_mutation": false,
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=143| "turn_secret_rotation": false,=REDACTED
|
||||
REC|SOURCE_TEXT|LABEL=HEAD:task.json|LINE=145| "home_router_mutation": false,
|
||||
CURRENT_EDGE_REFERENCE_FILE_COUNT=4
|
||||
REC|CURRENT_EDGE_REF_FILE|BASENAME=2026-08-17-snikket-edge-cutover-design.md|PARENT=specs|PATH_SHA=f0862c0e9d53ebf2bf9e6213cd190fc39de58a3f11c508d952aa26ad475d1e02
|
||||
REC|CURRENT_EDGE_REF_FILE|BASENAME=2026-08-17-snikket-post-cutover-hardening-design.md|PARENT=specs|PATH_SHA=7e742cf139b78adf59e860e331f4b8f02fbb75e42a5492dd969bbe003fdc65ec
|
||||
REC|CURRENT_EDGE_REF_FILE|BASENAME=task.json|PARENT=snikket-edge-cutover-v1|PATH_SHA=d0a271727e96d64818be706231c4f74d0dbe77bcadfaada5325e43b874fab0ba
|
||||
REC|CURRENT_EDGE_REF_FILE|BASENAME=cutover.py|PARENT=tools|PATH_SHA=6dbc303494115f30477da0b911dd387ed0e5959e1a3e322680980fb7cbb8b83a
|
||||
CURRENT_WGEDGE_EXACT_REFERENCE_COUNT=16
|
||||
DECISION=PASS_SNIKKET_WGEDGE_DESIGN_STATE_RCA
|
||||
NEXT_GATE=APPLY_CURRENT_SOURCE_DESIGN
|
||||
TASK_RESULT=SNIKKET_WGEDGE_DESIGN_STATE_RCA
|
||||
SOURCE_ROLLBACK_NETWORK_PRESENT=true
|
||||
SOURCE_ROLLBACK_USES_CLOUDFLARE=true
|
||||
ROLLBACK_STATE_PRESENT=true
|
||||
ROLLBACK_STATE_SHA=b4696a99b8e13042680d3c56537e0e5e5b6d3e7fae69e01fb8b8f60d68c39fc7
|
||||
ROLLBACK_STATE_MODE=600
|
||||
ROLLBACK_STATE_MTIME=1786953752
|
||||
ROLLBACK_STATE_JSON_VALID=true
|
||||
ROLLBACK_STATE_HAS_DNS_CONTENT=true
|
||||
ROLLBACK_STATE_HAS_DEFAULT_ROUTE=true
|
||||
ROLLBACK_OLD_ROUTE_SHA=7c5515603e424ad8e85718ba716657be12298988ee11416f41081ec82e023409
|
||||
ROLLBACK_HOME_IP_SHA=26ac437d63a8bcf254255cc970d7614e78bd0a67b97b5575a42a1c3ca7a301ee
|
||||
PVE01_IPIFY_RC=0
|
||||
PVE01_PUBLIC_IP_SHA=26ac437d63a8bcf254255cc970d7614e78bd0a67b97b5575a42a1c3ca7a301ee
|
||||
ROLLBACK_HOME_MATCHES_CURRENT_PVE01_PUBLIC=true
|
||||
VM150_QGA_TRANSPORT_RC=0
|
||||
REC|VM150|QGA_EXIT=0
|
||||
REC|VM150|DOMAIN_SHA=04cb4a04e408d91abb9c63701ae969abf16d8a12b6f4f144c5edf2c28e03256b
|
||||
REC|VM150|EDGE_EGRESS_UNIT_PRESENT=true
|
||||
REC|VM150|EDGE_EGRESS_ACTIVE=active
|
||||
REC|VM150|EDGE_EGRESS_ENABLED=enabled
|
||||
REC|VM150|EDGE_EGRESS_UNIT_SHA=83a20356e221dfb22ea2a0d99e327f7c2f791a3d3127a46af2d1625b33c95b5d
|
||||
REC|VM150|OLDGW_SHA=4f9da1283166a1e9f4e6bc7dd240c76aef85772177f717f92abb6e8e2bb8de90
|
||||
REC|VM150|NEWGW_SHA=bc517b4af3298846906234d3d697d3820b0b652ade1880c937c9d71cd802c834
|
||||
REC|VM150|OLDGW_PING_RC=1
|
||||
REC|VM150|CURRENT_GW_SHA=bc517b4af3298846906234d3d697d3820b0b652ade1880c937c9d71cd802c834
|
||||
REC|VM150|REC|CONTAINER|NAME=snikket|RUNNING=true|RESTARTS=0
|
||||
REC|VM150|REC|CONTAINER|NAME=snikket-proxy|RUNNING=true|RESTARTS=0
|
||||
REC|VM150|REC|CONTAINER|NAME=snikket-certs|RUNNING=true|RESTARTS=0
|
||||
REC|VM150|REC|CONTAINER|NAME=snikket-portal|RUNNING=true|RESTARTS=0
|
||||
REC|VM150|LOCAL_HTTPS_RC=0
|
||||
REC|VM150|LOCAL_HTTPS_CODE=302
|
||||
VM130_QGA_TRANSPORT_RC=0
|
||||
REC|VM130|QGA_EXIT=0
|
||||
REC|VM130|ROLE=VM130
|
||||
REC|VM130|WG_CONFIG_PRESENT=true
|
||||
REC|VM130|WG_BACKUP_PRESENT=true
|
||||
REC|VM130|WG_CONFIG_SHA=42b046d580b2ccd6af8f3573fba4882c71c92b2938f3fed8edf58258bbc89615
|
||||
REC|VM130|WG_BACKUP_SHA=9012ece867ad7efa1b2d07020c1cdfc9d3a63f86fde9117bdd7435eef29a9735
|
||||
REC|VM130|WG_BACKUP_MODE=600
|
||||
REC|VM130|PRIORITY101_COUNT=1
|
||||
REC|VM130|TABLE17777_DEFAULT_COUNT=1
|
||||
REC|VM130|WG_EDGE_ACTIVE=active
|
||||
CURRENT_AUTHORITATIVE_BEGET=true
|
||||
REC|DNS|ROLE=primary|A_COUNT=1|MATCH_ROLLBACK_HOME=true
|
||||
REC|DNS|ROLE=groups|A_COUNT=1|MATCH_ROLLBACK_HOME=true
|
||||
REC|DNS|ROLE=share|A_COUNT=1|MATCH_ROLLBACK_HOME=true
|
||||
BEGET_LOGIN_CANDIDATE_COUNT=0
|
||||
BEGET_PASSWORD_CANDIDATE_COUNT=0
|
||||
BEGET_CREDENTIALS_UNIQUE=false
|
||||
REC|HOME_TCP|PORT=443|OPEN=true|MSEC=1
|
||||
REC|HOME_TCP|PORT=5000|OPEN=true|MSEC=0
|
||||
REC|HOME_TCP|PORT=5222|OPEN=true|MSEC=0
|
||||
REC|HOME_TCP|PORT=5349|OPEN=false|ERR=TimeoutError
|
||||
ROLLBACK_PREFLIGHT_READY=false
|
||||
DECISION=PASS_SNIKKET_HOME_ROLLBACK_PREFLIGHT
|
||||
NEXT_GATE=ROLLBACK_PREFLIGHT_BLOCKER_REPAIR
|
||||
TASK_RESULT=SNIKKET_HOME_ROLLBACK_PREFLIGHT
|
||||
CHANGES_MADE=false
|
||||
ROLLBACK_STARTED=false
|
||||
ROLLBACK_RESTORED=null
|
||||
MUTATION_OUTCOME=NO_MUTATION
|
||||
HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-261006-SNIKKET-WGEDGE-DESIGN-STATE-RCA-99739R1","status":"OK","changes_made":false,"rollback_started":false,"rollback_restored":null}
|
||||
HOMELAB_RESULT_CONTRACT={"version":1,"command_id":"SUPPORT-261006-SNIKKET-HOME-ROLLBACK-PREFLIGHT-99740R1","status":"OK","changes_made":false,"rollback_started":false,"rollback_restored":null}
|
||||
|
||||
OUTPUT_END
|
||||
CHAT_OUTPUT_END
|
||||
|
||||
Reference in New Issue
Block a user