Prepare verified combined Coulomb attachment and content release
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a192e9-c28b-7533-bf25-e2341364c22a
This commit is contained in:
parent
c733e86b0f
commit
dc927d7751
16 changed files with 1105 additions and 4 deletions
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"schema": "coulomb.attachment-menu-source-validation.v1",
|
||||
"product_decision": "78175c34-58e1-4ad6-944d-0662c0462ae6",
|
||||
"full_main_gate": {
|
||||
"command": "TMPDIR=/var/tmp make check",
|
||||
"passed": 670,
|
||||
"failures": 0,
|
||||
"errors": 0,
|
||||
"skipped": 0,
|
||||
"log_sha256": "357547d34f7d73f750721338cff3e07439e8c710d0f1cf838541c1b175268335"
|
||||
},
|
||||
"isolated_release_gate": {
|
||||
"source": "1139a6d30eee4f75317b46bd45120a15d818455f",
|
||||
"command": "make check",
|
||||
"passed": 568,
|
||||
"failures": 0,
|
||||
"errors": 0,
|
||||
"skipped": 0,
|
||||
"log_sha256": "d9a9c8883f0d4021918c8600f9b5055cac24ca6b9943ee89db067f55d65ccdb1"
|
||||
},
|
||||
"checks": [
|
||||
"Author upload/remove; authorized reader download; foreign-tenant, outsider, revoked, archived and anonymous denial",
|
||||
"Stale page and CSRF refusal; immutable file names; 16 MiB limit; traversal and symlink denial",
|
||||
"Retained body/source dates and associations through edit/rename; removal keeps historical revision bytes",
|
||||
"Independent copy/move associations and managed files through 14 abrupt process deaths",
|
||||
"Upload recovery at partial bytes, complete bytes, stored revision and published page",
|
||||
"Real loopback browser upload/download/copy/move/remove and permission checks; no external requests"
|
||||
],
|
||||
"synthetic_fixtures_only": true,
|
||||
"production_deployed": false,
|
||||
"productive_user_acceptance": false
|
||||
}
|
||||
|
|
@ -0,0 +1,371 @@
|
|||
{
|
||||
"schema": "coulomb.backup-installation-independent-postflight.v1",
|
||||
"verified_at": "2026-10-31T17:30:18.219708+00:00",
|
||||
"status": "installed_files_and_inactive_units_verified",
|
||||
"proposal_digest": "sha256:8f442bf0ebed8bbf3b7f227b52081df52613f3f5f6874c4a59511cfc2ba06d42",
|
||||
"receipt_sha256": "96329afbd5662f71bf6d6b05c003f0810be12c10036f9cadb41cc373d3a1108b",
|
||||
"receipt": {
|
||||
"schema": "coulomb.backup-source-supervised-installation.v1",
|
||||
"proposal_digest": "sha256:8f442bf0ebed8bbf3b7f227b52081df52613f3f5f6874c4a59511cfc2ba06d42",
|
||||
"status": "sources_installed_units_inactive_verified",
|
||||
"preflight": {
|
||||
"units": {
|
||||
"coulomb-social-paired-backup.service": {
|
||||
"LoadState": "not-found",
|
||||
"ActiveState": "inactive",
|
||||
"SubState": "dead",
|
||||
"FragmentPath": "",
|
||||
"UnitFileState": ""
|
||||
},
|
||||
"coulomb-social-paired-backup.timer": {
|
||||
"LoadState": "not-found",
|
||||
"ActiveState": "inactive",
|
||||
"SubState": "dead",
|
||||
"FragmentPath": "",
|
||||
"UnitFileState": ""
|
||||
},
|
||||
"coulomb-social-backup-freshness.service": {
|
||||
"LoadState": "not-found",
|
||||
"ActiveState": "inactive",
|
||||
"SubState": "dead",
|
||||
"FragmentPath": "",
|
||||
"UnitFileState": ""
|
||||
},
|
||||
"coulomb-social-backup-freshness.timer": {
|
||||
"LoadState": "not-found",
|
||||
"ActiveState": "inactive",
|
||||
"SubState": "dead",
|
||||
"FragmentPath": "",
|
||||
"UnitFileState": ""
|
||||
},
|
||||
"coulomb-social-backup-alert@coulomb-social-paired-backup.service.service": {
|
||||
"LoadState": "not-found",
|
||||
"ActiveState": "inactive",
|
||||
"SubState": "dead",
|
||||
"FragmentPath": "",
|
||||
"UnitFileState": ""
|
||||
}
|
||||
},
|
||||
"capacity": {
|
||||
"state_bytes": 11259904,
|
||||
"state_reserve_bytes": 7532969984,
|
||||
"disk_reserve_bytes": 8606711808,
|
||||
"free_bytes": 115579949056,
|
||||
"free_inodes": 24523113,
|
||||
"filesystem_blocks_reserved": false
|
||||
},
|
||||
"sdk": {
|
||||
"boto3": "1.40.18",
|
||||
"botocore": "1.40.76"
|
||||
},
|
||||
"route": {
|
||||
"helm_revision": 6,
|
||||
"runtime_and_complete_resources_verified": true
|
||||
}
|
||||
},
|
||||
"timers_activated": false,
|
||||
"capture_executed": false,
|
||||
"email_sent": false,
|
||||
"retained_data_deleted": false,
|
||||
"started_at": "2026-10-31T17:22:48.757530+00:00",
|
||||
"capacity_profile": {
|
||||
"maximum_new_file_bytes": 1073741824,
|
||||
"state_budget_bytes": 8589934592,
|
||||
"minimum_free_bytes": 8589934592,
|
||||
"minimum_free_inodes": 1024,
|
||||
"control_margin_bytes": 16777216
|
||||
},
|
||||
"founder_confirmed_profile_and_installation": true,
|
||||
"route_postflight": {
|
||||
"helm_revision": 6,
|
||||
"runtime_and_complete_resources_verified": true
|
||||
},
|
||||
"verified_targets": 19,
|
||||
"units": {
|
||||
"coulomb-social-paired-backup.service": {
|
||||
"LoadState": "loaded",
|
||||
"ActiveState": "inactive",
|
||||
"SubState": "dead",
|
||||
"FragmentPath": "/etc/systemd/system/coulomb-social-paired-backup.service",
|
||||
"UnitFileState": "static"
|
||||
},
|
||||
"coulomb-social-paired-backup.timer": {
|
||||
"LoadState": "loaded",
|
||||
"ActiveState": "inactive",
|
||||
"SubState": "dead",
|
||||
"FragmentPath": "/etc/systemd/system/coulomb-social-paired-backup.timer",
|
||||
"UnitFileState": "disabled"
|
||||
},
|
||||
"coulomb-social-backup-freshness.service": {
|
||||
"LoadState": "loaded",
|
||||
"ActiveState": "inactive",
|
||||
"SubState": "dead",
|
||||
"FragmentPath": "/etc/systemd/system/coulomb-social-backup-freshness.service",
|
||||
"UnitFileState": "static"
|
||||
},
|
||||
"coulomb-social-backup-freshness.timer": {
|
||||
"LoadState": "loaded",
|
||||
"ActiveState": "inactive",
|
||||
"SubState": "dead",
|
||||
"FragmentPath": "/etc/systemd/system/coulomb-social-backup-freshness.timer",
|
||||
"UnitFileState": "disabled"
|
||||
},
|
||||
"coulomb-social-backup-alert@coulomb-social-paired-backup.service.service": {
|
||||
"LoadState": "loaded",
|
||||
"ActiveState": "inactive",
|
||||
"SubState": "dead",
|
||||
"FragmentPath": "/etc/systemd/system/coulomb-social-backup-alert@.service",
|
||||
"UnitFileState": "static"
|
||||
}
|
||||
},
|
||||
"updated_at": "2026-10-31T17:22:54.560675+00:00"
|
||||
},
|
||||
"nested_receipt_sha256": "795d9eb672b24495c77ad636a210c5d2022c8c3124d276920db7eda02257e519",
|
||||
"verified_targets": 19,
|
||||
"installed_fingerprints": {
|
||||
"/opt/coulomb-social-backup/paired-backup.py": {
|
||||
"exists": true,
|
||||
"sha256": "d161c742d1a6a182460a57d0a1719591ab58fc94006f55169ad3d74442a93630",
|
||||
"mode": 384,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 534009,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368826077309
|
||||
},
|
||||
"/opt/coulomb-social-backup/snapshot-content-and-db.py": {
|
||||
"exists": true,
|
||||
"sha256": "dcc8dd2a3989f279597595f9260b31b24fcc9b6dc787f04c17ef0491c53d830d",
|
||||
"mode": 384,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 549255,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793430923413704430
|
||||
},
|
||||
"/opt/coulomb-social-backup/mirror-paired-backup.py": {
|
||||
"exists": true,
|
||||
"sha256": "9ceb26d9083af016c4b787907e4dce7bdf437c782fb2d15eb28d9e334e6e431c",
|
||||
"mode": 384,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 549201,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368831077393
|
||||
},
|
||||
"/opt/coulomb-social-backup/check-paired-backup-health.py": {
|
||||
"exists": true,
|
||||
"sha256": "2d40ec6e4c59ea7fe1d46065d197b9a87ca6811f023cc6f3e20e4184a3490566",
|
||||
"mode": 384,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 549309,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368836077477
|
||||
},
|
||||
"/opt/coulomb-social-backup/backup_capacity.py": {
|
||||
"exists": true,
|
||||
"sha256": "cb699a79e67b129239b5aa5d6f3b0d4ffaa9773a8b073227ad17fdecb5b9d893",
|
||||
"mode": 384,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 549354,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368843077594
|
||||
},
|
||||
"/opt/coulomb-social-backup/mirror-platform-runtime.json": {
|
||||
"exists": true,
|
||||
"sha256": "9253c5f6e956b67f499d3e12d2851be7fabd3bc56b00496b8810bbd0be8209f1",
|
||||
"mode": 384,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 549355,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368847077662
|
||||
},
|
||||
"/opt/coulomb-social-backup/backup_alerts.py": {
|
||||
"exists": true,
|
||||
"sha256": "07522437d4276b92f0a44149adc6c9e81bb18dbe59ce0f1f9e58a48347700d0e",
|
||||
"mode": 384,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 549359,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368887078332
|
||||
},
|
||||
"/opt/coulomb-social-backup/notify-backup-alert.py": {
|
||||
"exists": true,
|
||||
"sha256": "0bd53bc5ad22d8bcb0326fb18a17737744b06416fe785dad077308e45f051d5a",
|
||||
"mode": 384,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 549360,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368891078399
|
||||
},
|
||||
"/opt/coulomb-social-backup/observe-backup-alerts.py": {
|
||||
"exists": true,
|
||||
"sha256": "17caf4fa65283242f618b039ff1d018801c9890ea2a9178912cbdd4b50ee2664",
|
||||
"mode": 384,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 549361,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368895078466
|
||||
},
|
||||
"/opt/railiance-platform/scripts/application_recovery_identities.py": {
|
||||
"exists": true,
|
||||
"sha256": "20f56255ed6eeec4aafe33f142bc3ee03f623d4957a7b0cabb741d340f15f79d",
|
||||
"mode": 384,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 549356,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368852077745
|
||||
},
|
||||
"/opt/railiance-platform/scripts/application_recovery_mirror.py": {
|
||||
"exists": true,
|
||||
"sha256": "d48ab95e89b9eeae36269d853ebe4c44c22e1f57d4e14224f03d0b9aeeb34178",
|
||||
"mode": 384,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 549357,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368857077829
|
||||
},
|
||||
"/opt/railiance-platform/scripts/application_recovery_resources.py": {
|
||||
"exists": true,
|
||||
"sha256": "ab70ec341e738272730eb0daf76840d0bca807caeb3c4e4c2357f162fbed4498",
|
||||
"mode": 384,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 549358,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368862077913
|
||||
},
|
||||
"/opt/railiance-platform/scripts/primary_application_archive.py": {
|
||||
"exists": true,
|
||||
"sha256": "a3f0a61e869a6012edb4b5288be14e3b0c4a9a1273b090320ab146d12e5aa94d",
|
||||
"mode": 420,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 540610,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1791537447437616251
|
||||
},
|
||||
"/etc/systemd/system/coulomb-social-backup-freshness.service": {
|
||||
"exists": true,
|
||||
"sha256": "8d6278c2cbca7f48b659c239c1d1e181fa4b9cf023fe7429850e294c6cd84d0e",
|
||||
"mode": 420,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 19366,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368868078014
|
||||
},
|
||||
"/etc/systemd/system/coulomb-social-paired-backup.service": {
|
||||
"exists": true,
|
||||
"sha256": "8b01b788bb08f453fdd4807104185c89411e0b0b4dedee9240f14f110ceb5513",
|
||||
"mode": 420,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 14867,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368873078098
|
||||
},
|
||||
"/etc/systemd/system/coulomb-social-backup-freshness.timer": {
|
||||
"exists": true,
|
||||
"sha256": "75d1d0721c07fdd0703910c06bb8a678396440e7d95411a37ee7de4938f3ac31",
|
||||
"mode": 420,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 19367,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368878078181
|
||||
},
|
||||
"/etc/systemd/system/coulomb-social-paired-backup.timer": {
|
||||
"exists": true,
|
||||
"sha256": "5e87235e66f89a64a972562d6f163f62420628fc44fb7fd8d603a96c347dfbb9",
|
||||
"mode": 420,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 19368,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368882078248
|
||||
},
|
||||
"/etc/systemd/system/coulomb-social-backup-alert@.service": {
|
||||
"exists": true,
|
||||
"sha256": "4bfa019d29b1d0de278f03553602a5e824de50ed99ebcf3b5035cf4d5b06fe98",
|
||||
"mode": 420,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 19370,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368899078533
|
||||
},
|
||||
"/etc/coulomb-social-backup/alerting.env": {
|
||||
"exists": true,
|
||||
"sha256": "509844b5c8ef618b812d52f32e19c3c559623636dca62f7b16f437aa90cc0458",
|
||||
"mode": 384,
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"inode": 19369,
|
||||
"device": 2049,
|
||||
"mtime_ns": 1793467368904078617
|
||||
}
|
||||
},
|
||||
"units": {
|
||||
"coulomb-social-paired-backup.service": {
|
||||
"LoadState": "loaded",
|
||||
"ActiveState": "inactive",
|
||||
"SubState": "dead",
|
||||
"FragmentPath": "/etc/systemd/system/coulomb-social-paired-backup.service",
|
||||
"UnitFileState": "static"
|
||||
},
|
||||
"coulomb-social-paired-backup.timer": {
|
||||
"LoadState": "loaded",
|
||||
"ActiveState": "inactive",
|
||||
"SubState": "dead",
|
||||
"FragmentPath": "/etc/systemd/system/coulomb-social-paired-backup.timer",
|
||||
"UnitFileState": "disabled"
|
||||
},
|
||||
"coulomb-social-backup-freshness.service": {
|
||||
"LoadState": "loaded",
|
||||
"ActiveState": "inactive",
|
||||
"SubState": "dead",
|
||||
"FragmentPath": "/etc/systemd/system/coulomb-social-backup-freshness.service",
|
||||
"UnitFileState": "static"
|
||||
},
|
||||
"coulomb-social-backup-freshness.timer": {
|
||||
"LoadState": "loaded",
|
||||
"ActiveState": "inactive",
|
||||
"SubState": "dead",
|
||||
"FragmentPath": "/etc/systemd/system/coulomb-social-backup-freshness.timer",
|
||||
"UnitFileState": "disabled"
|
||||
},
|
||||
"coulomb-social-backup-alert@coulomb-social-paired-backup.service.service": {
|
||||
"LoadState": "loaded",
|
||||
"ActiveState": "inactive",
|
||||
"SubState": "dead",
|
||||
"FragmentPath": "/etc/systemd/system/coulomb-social-backup-alert@.service",
|
||||
"UnitFileState": "static"
|
||||
}
|
||||
},
|
||||
"route": {
|
||||
"helm_revision": 6,
|
||||
"runtime_and_complete_resources_verified": true
|
||||
},
|
||||
"capacity": {
|
||||
"state_bytes": 11259904,
|
||||
"state_reserve_bytes": 7532969984,
|
||||
"disk_reserve_bytes": 8606711808,
|
||||
"free_bytes": 115555618816,
|
||||
"free_inodes": 24523041,
|
||||
"filesystem_blocks_reserved": false
|
||||
},
|
||||
"sdk": {
|
||||
"boto3": "1.40.18",
|
||||
"botocore": "1.40.76"
|
||||
},
|
||||
"runtime_modified_by_verification": false
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"schema": "coulomb.backup-route-independent-postflight.v1",
|
||||
"verified_at": "2026-10-31T17:19:36.926769+00:00",
|
||||
"status": "durable_receipt_and_live_route_verified",
|
||||
"execution_digest": "sha256:4d8481061dc9ce6835169defc96887945052332a0db8d4234ae84032d63cc328",
|
||||
"receipt": {
|
||||
"schema": "rapp-telemetry.backup-route-execution.v1",
|
||||
"execution_digest": "sha256:4d8481061dc9ce6835169defc96887945052332a0db8d4234ae84032d63cc328",
|
||||
"proposal_digest": "sha256:4bcad54f7b8e1e77b94112e452cbb58eaf8e882dc10305129c5f9ca69f014a66",
|
||||
"status": "backup_email_route_deployed_verified",
|
||||
"timers_activated": false,
|
||||
"notification_sent_by_helper": false,
|
||||
"production_data_restored": false,
|
||||
"started_at": "2026-10-31T17:17:13.743344+00:00",
|
||||
"helm_revision": 6,
|
||||
"verified_resource_count": 87,
|
||||
"after_resources_sha256": "600c4998e54b8e11845849c7d8e4c6b6699556c21f5df6ca79bb86b2e8d1683f",
|
||||
"live_desired_fields_verified": true,
|
||||
"runtime_config_verified": true,
|
||||
"existing_image_and_pvc_preserved": true,
|
||||
"completed_at": "2026-10-31T17:17:31.488654+00:00"
|
||||
},
|
||||
"receipt_sha256": "c26d636f59109956f281ad46f4885c4db800a9553cf05cac324aa3155ef7ac40",
|
||||
"original_execution_packet_matches": true,
|
||||
"live_desired_fields_verified": true,
|
||||
"runtime_config_verified": true,
|
||||
"existing_image_and_pvc_preserved": true,
|
||||
"runtime_modified_by_verification": false
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"schema": "coulomb.content-acceptance-build.v1",
|
||||
"completed_at": "2026-10-31T18:38:08.525103+00:00",
|
||||
"source": "1139a6d30eee4f75317b46bd45120a15d818455f",
|
||||
"image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:7906f461bc8d2d5204fd4fde67a251850f725b914452a66172919d6853672ed5",
|
||||
"build_context": "clean restricted git archive",
|
||||
"source_full_gate_tests": 568,
|
||||
"runtime_packages_and_python_unchanged": true,
|
||||
"runtime": {
|
||||
"python": "3.12.16",
|
||||
"distributions": {
|
||||
"h11": "0.16.0",
|
||||
"httpcore": "1.0.9",
|
||||
"psycopg": "3.3.4",
|
||||
"joserfc": "1.7.4",
|
||||
"anyio": "4.14.2",
|
||||
"cryptography": "50.0.0",
|
||||
"idna": "3.18",
|
||||
"certifi": "2026.7.22",
|
||||
"packaging": "26.3",
|
||||
"python-decouple": "3.8",
|
||||
"psycopg-binary": "3.3.4",
|
||||
"sqlparse": "0.5.5",
|
||||
"whitenoise": "6.12.0",
|
||||
"cffi": "2.1.1",
|
||||
"markdown": "3.10.3",
|
||||
"webencodings": "0.5.1",
|
||||
"pycparser": "3.0",
|
||||
"bleach": "6.4.0",
|
||||
"authlib": "1.7.2",
|
||||
"django": "6.1",
|
||||
"typing_extensions": "4.16.0",
|
||||
"gunicorn": "26.0.0",
|
||||
"asgiref": "3.12.1",
|
||||
"httpx": "0.28.1",
|
||||
"dj-database-url": "3.1.2"
|
||||
}
|
||||
},
|
||||
"django_checks": {
|
||||
"check": "System check identified no issues (0 silenced).",
|
||||
"makemigrations": "No changes detected"
|
||||
},
|
||||
"new_database_migrations": false,
|
||||
"production_deployed": false
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"schema": "coulomb.packaged-source-provenance.v1",
|
||||
"image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:7906f461bc8d2d5204fd4fde67a251850f725b914452a66172919d6853672ed5",
|
||||
"source": "1139a6d30eee4f75317b46bd45120a15d818455f",
|
||||
"packaged_file_count": 79,
|
||||
"all_packaged_source_bytes_match": true,
|
||||
"source_revision_label_verified": true,
|
||||
"registry_digest_resolves": true,
|
||||
"application_source_overlay": false,
|
||||
"manifest_sha256": "2eca0618df5bdf35928869c3b848be36190065a4cca8f855bba372df6c516556"
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"schema": "coulomb.packaged-content-acceptance-recovery.v1",
|
||||
"status": "packaged_recovered_export_and_views_verified",
|
||||
"source": "1139a6d30eee4f75317b46bd45120a15d818455f",
|
||||
"image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:7906f461bc8d2d5204fd4fde67a251850f725b914452a66172919d6853672ed5",
|
||||
"restore_receipt_sha256": "3d6fe0b5d7426c9fb39ba22f18770319e0c89ba1981c61db171199d3b4e68524",
|
||||
"retained_point_captured_at": "2026-10-31T07:13:52Z",
|
||||
"candidate_application": {
|
||||
"business_tables": 12,
|
||||
"migration_rows_sha256": "43471516387c0e2a3d35971033ed6af330e2963efe4da93293d97633825d04af",
|
||||
"business_rows": 92,
|
||||
"business_rows_sha256": "6243955479f7861fcdcd79b62f7f1e9f9a27c05a17bd2c17b792ebc98b2fa7b6",
|
||||
"content_files": 86,
|
||||
"content_files_sha256": "ed535246f4e8f46fcd7ce01f936127996aff873c6936b297f7272194b594aeda",
|
||||
"global_slug_constraint": true,
|
||||
"tenant_slug_constraint": true,
|
||||
"migration_0003_applied": true,
|
||||
"duplicate_slug_groups": 0,
|
||||
"actual_owner_pages_rendered": 40,
|
||||
"unsaved_outsider_page_denials": 40,
|
||||
"production_identity_or_grant_created": false
|
||||
},
|
||||
"previous_image_application": {
|
||||
"business_tables": 12,
|
||||
"migration_rows_sha256": "43471516387c0e2a3d35971033ed6af330e2963efe4da93293d97633825d04af",
|
||||
"business_rows": 92,
|
||||
"business_rows_sha256": "6243955479f7861fcdcd79b62f7f1e9f9a27c05a17bd2c17b792ebc98b2fa7b6",
|
||||
"content_files": 86,
|
||||
"content_files_sha256": "ed535246f4e8f46fcd7ce01f936127996aff873c6936b297f7272194b594aeda",
|
||||
"global_slug_constraint": true,
|
||||
"tenant_slug_constraint": true,
|
||||
"migration_0003_applied": true,
|
||||
"duplicate_slug_groups": 0,
|
||||
"actual_owner_pages_rendered": 40,
|
||||
"unsaved_outsider_page_denials": 40,
|
||||
"production_identity_or_grant_created": false
|
||||
},
|
||||
"client_export": {
|
||||
"status": "recovered_client_export_verified",
|
||||
"schema": "coulomb.client-dataset-export.v1",
|
||||
"content_files": 85,
|
||||
"records": {
|
||||
"members.user": 1,
|
||||
"members.member": 1,
|
||||
"spaces.space": 1,
|
||||
"spaces.spacemembership": 1
|
||||
},
|
||||
"admin_events": 0,
|
||||
"archive_sha256": "eb982edcdb94c976ab3d4e9797e4c34eb72a3ee3886a37e64508744ac172a8a8",
|
||||
"offboarding_complete": false,
|
||||
"all_source_tables_compared": 13,
|
||||
"all_source_files_compared": 86,
|
||||
"archive_member_hashes_verified": true,
|
||||
"selected_client_content_complete_locally": true,
|
||||
"source_sql_and_content_unchanged": true,
|
||||
"external_bindings_require_review": 0,
|
||||
"sessions_and_credentials_excluded": true
|
||||
},
|
||||
"source_content_files_unchanged": 86,
|
||||
"all_tables_unchanged": true,
|
||||
"application_source_overlay": false,
|
||||
"network_internal": true,
|
||||
"published_ports": 0,
|
||||
"production_access": false,
|
||||
"production_restore": false,
|
||||
"driver_sha256": "da85e5f7d5cf68f599a897a932d51399340bdd026a7cddf9603bef4aeb40909a"
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"baseline_revision": 19,
|
||||
"baseline_helm_manifest_sha256": "93cb277abd1aea0657be482e458dcfb268fe0bfbd45d90aa1faedcc7f5bce499",
|
||||
"deployment_uid": "2dbe661a-d232-4477-bbd1-833813077fbe",
|
||||
"baseline_spec_sha256": "42e091e52d5dae3c1f986e4898c62057fa80846adfce049a75d8fbd4681180ea",
|
||||
"candidate_spec_sha256": "8d79c64cff4bd2c62f03494e80847dc99b965ddabf35645da67e8d1020220798",
|
||||
"old_image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:522bcd7fce92436765a60c1e4afa2598f3cc40913352153ff1c4319a99ca92ed",
|
||||
"expected_data": {
|
||||
"business_tables": 12,
|
||||
"migration_rows_sha256": "43471516387c0e2a3d35971033ed6af330e2963efe4da93293d97633825d04af",
|
||||
"business_rows": 93,
|
||||
"business_rows_sha256": "7953b37b02b80d89ca6869dab6b2b0b996541de20ca0dd1b294a5f25572fb2ca",
|
||||
"content_files": 86,
|
||||
"content_files_sha256": "ed535246f4e8f46fcd7ce01f936127996aff873c6936b297f7272194b594aeda",
|
||||
"global_slug_constraint": true,
|
||||
"tenant_slug_constraint": true,
|
||||
"migration_0003_applied": true,
|
||||
"duplicate_slug_groups": 0
|
||||
},
|
||||
"image_only_server_preview": true
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"schema": "coulomb.packaged-content-acceptance-tests.v1",
|
||||
"image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:7906f461bc8d2d5204fd4fde67a251850f725b914452a66172919d6853672ed5",
|
||||
"source": "1139a6d30eee4f75317b46bd45120a15d818455f",
|
||||
"tests": 110,
|
||||
"failures": 0,
|
||||
"errors": 0,
|
||||
"skipped": 0,
|
||||
"network": "none",
|
||||
"read_only_root": true,
|
||||
"application_source_overlay": false,
|
||||
"synthetic_fixtures_only": true
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"schema": "coulomb.packaged-content-lifecycle-tests.v1",
|
||||
"source": "23ffe2cf4b214666754a2420558943438e54251a",
|
||||
"image_id": "sha256:522bcd7fce92436765a60c1e4afa2598f3cc40913352153ff1c4319a99ca92ed",
|
||||
"tests": 29,
|
||||
"failures": 4,
|
||||
"expected_baseline_regressions": true,
|
||||
"failed_nodes": [
|
||||
"test_process_death_during_copy_or_move_is_recoverable[copy_page-during_first_asset]",
|
||||
"test_process_death_during_copy_or_move_is_recoverable[copy_page-during_second_asset]",
|
||||
"test_process_death_during_copy_or_move_is_recoverable[transfer_page-during_first_asset]",
|
||||
"test_process_death_during_copy_or_move_is_recoverable[transfer_page-during_second_asset]"
|
||||
],
|
||||
"errors": 0,
|
||||
"skipped": 0,
|
||||
"network": "none",
|
||||
"read_only_root": true,
|
||||
"application_source_overlay": false,
|
||||
"test_tooling_injected": true,
|
||||
"application_modules_from_image_verified": true,
|
||||
"production_access": false,
|
||||
"junit_sha256": "edc52bd3a321d028d255b3d478020b3383d94747957ffe2985583b1f0741cb85",
|
||||
"driver_sha256": "85b65114997c7e7c5323cb77a0043e495ec132506eef07dd394c6a6361380d36",
|
||||
"test_source_sha256": "84a25a22a3cbda397e39c0508db8ea5aa90e6c467ccfa7da2b568d174d1ec449"
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"changed_columns": {
|
||||
"django_session": [
|
||||
"session_key",
|
||||
"session_data",
|
||||
"expire_date"
|
||||
],
|
||||
"members_member": [
|
||||
"updated_at",
|
||||
"last_login_at"
|
||||
],
|
||||
"members_user": [
|
||||
"last_login"
|
||||
]
|
||||
},
|
||||
"file_changes": [],
|
||||
"retained_fingerprint": {
|
||||
"business_tables": 12,
|
||||
"migration_rows_sha256": "43471516387c0e2a3d35971033ed6af330e2963efe4da93293d97633825d04af",
|
||||
"business_rows": 92,
|
||||
"business_rows_sha256": "6243955479f7861fcdcd79b62f7f1e9f9a27c05a17bd2c17b792ebc98b2fa7b6",
|
||||
"content_files": 86,
|
||||
"content_files_sha256": "ed535246f4e8f46fcd7ce01f936127996aff873c6936b297f7272194b594aeda",
|
||||
"global_slug_constraint": true,
|
||||
"tenant_slug_constraint": true,
|
||||
"migration_0003_applied": true,
|
||||
"duplicate_slug_groups": 0
|
||||
},
|
||||
"schema": "coulomb.content-release-row-drift.v1",
|
||||
"changed_tables": [
|
||||
{
|
||||
"table": "django_session",
|
||||
"retained_rows": 42,
|
||||
"current_rows": 43,
|
||||
"retained_sha256": "c958e33ec782f9f2fd1b3cceba4a64da0038fde51050f25905ae42de91ca6dde",
|
||||
"current_sha256": "594e246ef6297d9be9b6e8d9eda076a5b2ab36afb9263606b719f64f51293ba6"
|
||||
},
|
||||
{
|
||||
"table": "members_member",
|
||||
"retained_rows": 1,
|
||||
"current_rows": 1,
|
||||
"retained_sha256": "4d465d2b9d1e6311e505f861f2ed4b67763a545a965f9a7d0c586a3d07e3e9a3",
|
||||
"current_sha256": "ab82b3f2c5e49f8634c598c9642894747f4b6fcff0f5230ac27f41939feb8640"
|
||||
},
|
||||
{
|
||||
"table": "members_user",
|
||||
"retained_rows": 1,
|
||||
"current_rows": 1,
|
||||
"retained_sha256": "81ccb3a40191e910a68c101896df518a588c00231728934c4c900577f8ae4f12",
|
||||
"current_sha256": "0fc7a71b4b80a71fbedce527bbd2cae3858cf6a062e5714fc231be13ff987256"
|
||||
}
|
||||
],
|
||||
"all_other_business_tables_equal": true,
|
||||
"migration_history_equal": true,
|
||||
"content_equal": true,
|
||||
"retained_point": "2026-10-31T07:13:52Z",
|
||||
"current_business_rows": 93,
|
||||
"current_business_rows_sha256": "7953b37b02b80d89ca6869dab6b2b0b996541de20ca0dd1b294a5f25572fb2ca",
|
||||
"private_row_values_printed": false,
|
||||
"production_changes": false
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"schema": "coulomb.content-lifecycle-validation.v1",
|
||||
"recorded_at": "2026-10-31T11:54:24.215512+00:00",
|
||||
"status": "source_fix_verified",
|
||||
"workplan_task": "CSOC-WP-0013-T05",
|
||||
"bug": "A process exit during attachment creation left bytes absent from the copy/move cleanup journal; the orphan blocked retry.",
|
||||
"regression_observed_before_fix": {
|
||||
"baseline": "f70708839cd5ca43310f6891c8d94aaff915139c",
|
||||
"operations": [
|
||||
"copy_page",
|
||||
"transfer_page"
|
||||
],
|
||||
"interruption": "partial first attachment flushed, immediate os._exit(86)",
|
||||
"result": "both failed because the partial destination survived recovery"
|
||||
},
|
||||
"fix": [
|
||||
"Refuse existing attachment entries before recording cleanup authority.",
|
||||
"Persist intended new attachment name before exclusive creation under the content writer lock.",
|
||||
"Flush recovery and attachment directory entries before destination publication."
|
||||
],
|
||||
"focused_cases": {
|
||||
"total": 29,
|
||||
"abrupt_child_process_exit": 14,
|
||||
"existing_destination_collision": 8,
|
||||
"prior_retention_and_recovery": 7
|
||||
},
|
||||
"full_gate": {
|
||||
"command": "make check",
|
||||
"tests": 546,
|
||||
"failures": 0,
|
||||
"errors": 0,
|
||||
"skipped": 0,
|
||||
"warnings": 69,
|
||||
"junit_sha256": "dd3d0433c8109f00f6dddd119cfdf8281915f94da2da1f5e6009c31cfe76c65b",
|
||||
"log_sha256": "eb59a394c95c5307c17069874640d1655ef61c5aa7bb426ef6d21db4929f748e"
|
||||
},
|
||||
"files": [
|
||||
{
|
||||
"path": "coulomb_social/apps/spaces/pageops.py",
|
||||
"sha256": "055ef25b5efc75798cf17ffa68739de4d4099d2cab4d041e7c7eacdfaf43803e"
|
||||
},
|
||||
{
|
||||
"path": "tests/test_content_recovery.py",
|
||||
"sha256": "84a25a22a3cbda397e39c0508db8ea5aa90e6c467ccfa7da2b568d174d1ec449"
|
||||
}
|
||||
],
|
||||
"policy": "User accepted retain-all default and separately reviewed manual cutoff; keep live page and all history of deleted pages.",
|
||||
"live_purge_authorized": false,
|
||||
"live_purge_executed": false,
|
||||
"production_deployed": false,
|
||||
"productive_acceptance": false,
|
||||
"limits": [
|
||||
"Child process termination on synthetic local files is proved; physical power-loss durability is not experimentally proved.",
|
||||
"Cooperating application/import writers must use the content writer lock.",
|
||||
"Release delivery and productive copy/move review remain open."
|
||||
],
|
||||
"policy_decision_id": "c3a191f2-ce06-483f-82d7-ef8c54ea0d5e"
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"schema": "coulomb.ordered-list-fidelity.v1",
|
||||
"verified_at": "2026-10-31T17:20:32.943192+00:00",
|
||||
"source_articles_sha256": "f33967c79c0f8a60a7d504f5d5e4082f8bc9e3c34f6a3160cb200fd380831d62",
|
||||
"prior_audit_sha256": "3926e24a3b903f5e1d1c7133dc5f9df1e958183432c5131949ce838eb60acf1e",
|
||||
"current_audit_sha256": "d8f382e24d7adfe3c43dc71f32f8f6e647bf68239cbcdc6769a6c8fb85d666b9",
|
||||
"records": 245,
|
||||
"rendered_cards_verified": 242,
|
||||
"source_bodies_unchanged": true,
|
||||
"missing_bodies_retained": 3,
|
||||
"ordered_list_starts_restored": 15,
|
||||
"affected_records": 4,
|
||||
"markup_change_cases_before": 6,
|
||||
"markup_change_cases_after": 3,
|
||||
"remaining_removed_tags": {
|
||||
"topic": 3
|
||||
},
|
||||
"remaining_removed_attributes": [
|
||||
{
|
||||
"tag": "topic",
|
||||
"attribute": "name",
|
||||
"count": 2
|
||||
}
|
||||
],
|
||||
"private_review_directory": "~/.config/coulomb-social/auth/exports/rendering-review-20261031-numbering",
|
||||
"source_hashes": {
|
||||
"coulomb_social/apps/spaces/content.py": "5d6bb5c800b3e776fff385fa73284f4916403676dc2a8bc06b8fadc7d2387633",
|
||||
"tests/test_rendering_audit.py": "ae092753f4d1d006bb88f1ce11581975c105c5231819f9409ddaaf2fc83d32f5"
|
||||
},
|
||||
"validation": {
|
||||
"focused_passed": 14,
|
||||
"full_gate_passed": 650,
|
||||
"full_gate_warnings": 69,
|
||||
"failures": 0,
|
||||
"errors": 0,
|
||||
"skipped": 0,
|
||||
"full_gate_seconds": 91.85
|
||||
},
|
||||
"production_deployed": false,
|
||||
"original_bubble_render_compared": false,
|
||||
"productive_fidelity_accepted": false
|
||||
}
|
||||
175
release/content-acceptance-snapshot.py
Normal file
175
release/content-acceptance-snapshot.py
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Node-side quiesced coulomb-social snapshot. Binary output stays private.
|
||||
|
||||
Run on railiance01 after reviewed live approval. Does not restore production.
|
||||
Default is server dry-run; --execute briefly pauses the app and captures a
|
||||
paired pg_dump/content archive. A separate isolated restore must validate it.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import fcntl
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import signal
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
NS = 'coulomb-social'
|
||||
IMAGE = ('forgejo.coulomb.social/coulomb/coulomb-social@sha256:'
|
||||
'7906f461bc8d2d5204fd4fde67a251850f725b914452a66172919d6853672ed5')
|
||||
CLUSTER_UID = 'a553c742-0115-43d4-99a4-a5ca56fe0786'
|
||||
LOCK_PATH = Path('/var/lib/coulomb-social-backup/snapshot.lock')
|
||||
|
||||
|
||||
class Refused(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
def run(args: list[str], *, payload: bytes | None = None, timeout: int = 180) -> bytes:
|
||||
p = subprocess.run(args, input=payload, capture_output=True, timeout=timeout)
|
||||
if p.returncode:
|
||||
raise Refused('command_failed')
|
||||
return p.stdout
|
||||
|
||||
|
||||
def k(*args: str, payload: bytes | None = None) -> bytes:
|
||||
return run(['kubectl', *args], payload=payload)
|
||||
|
||||
|
||||
def document(*args: str) -> dict:
|
||||
return json.loads(k(*args, '-o', 'json'))
|
||||
|
||||
|
||||
def private_write(path: Path, value: bytes) -> None:
|
||||
fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
|
||||
with os.fdopen(fd, 'wb') as f:
|
||||
f.write(value)
|
||||
|
||||
|
||||
def snapshot() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--execute', action='store_true')
|
||||
parser.add_argument('--destination', type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
os.environ['KUBECONFIG'] = '/etc/rancher/k3s/k3s.yaml'
|
||||
started = time.monotonic()
|
||||
if document('get', 'namespace', 'kube-system')['metadata']['uid'] != CLUSTER_UID:
|
||||
raise Refused('wrong_cluster')
|
||||
dep = document('get', 'deployment', 'coulomb-social', '-n', NS)
|
||||
spec = dep['spec']['template']['spec']
|
||||
if dep['spec']['replicas'] != 1 or spec['containers'][0]['image'] != IMAGE:
|
||||
raise Refused('unexpected_release')
|
||||
if document('get', 'pvc', 'coulomb-social-content', '-n', NS)['status']['phase'] != 'Bound':
|
||||
raise Refused('pvc_not_bound')
|
||||
cluster = document('get', 'cluster', 'apps-pg', '-n', 'databases')
|
||||
primary = cluster['status']['currentPrimary']
|
||||
name = 'csoc-paired-snapshot-' + time.strftime('%Y%m%d%H%M%S', time.gmtime())
|
||||
pod = {
|
||||
'apiVersion': 'v1', 'kind': 'Pod',
|
||||
'metadata': {'name': name, 'namespace': NS, 'labels': {'csoc-recovery': name}},
|
||||
'spec': {
|
||||
'restartPolicy': 'Never', 'automountServiceAccountToken': False,
|
||||
'securityContext': {'runAsNonRoot': True, 'runAsUser': 10001,
|
||||
'runAsGroup': 10001, 'fsGroup': 10001,
|
||||
'fsGroupChangePolicy': 'OnRootMismatch'},
|
||||
'containers': [{'name': 'snapshot', 'image': IMAGE,
|
||||
'command': ['python', '-c', 'import time;time.sleep(1800)'],
|
||||
'resources': {'requests': {'cpu': '10m', 'memory': '64Mi'},
|
||||
'limits': {'cpu': '100m', 'memory': '256Mi'}},
|
||||
'securityContext': {'allowPrivilegeEscalation': False,
|
||||
'readOnlyRootFilesystem': True,
|
||||
'capabilities': {'drop': ['ALL']}},
|
||||
'volumeMounts': [{'name': 'content', 'mountPath': '/snapshot', 'readOnly': True}]}],
|
||||
'volumes': [{'name': 'content', 'persistentVolumeClaim':
|
||||
{'claimName': 'coulomb-social-content', 'readOnly': True}}],
|
||||
},
|
||||
}
|
||||
body = json.dumps(pod).encode()
|
||||
k('create', '--dry-run=server', '-f', '-', payload=body)
|
||||
if not args.execute:
|
||||
print(json.dumps({'status': 'reviewed', 'server_dry_run': True,
|
||||
'image_pinned': True, 'pvc_read_only': True,
|
||||
'db_scope': 'coulomb_social_db', 'replicas_restored_to': 1}))
|
||||
return 0
|
||||
dest = args.destination
|
||||
if not dest.is_absolute() or dest.exists():
|
||||
raise Refused('destination_must_be_new_absolute_directory')
|
||||
dest.mkdir(mode=0o700)
|
||||
paused = False
|
||||
created = False
|
||||
receipt = {'status': 'incomplete', 'app': 'coulomb-social',
|
||||
'database': 'coulomb_social_db', 'image': IMAGE,
|
||||
'started_at': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}
|
||||
try:
|
||||
paused = True
|
||||
k('scale', 'deployment/coulomb-social', '-n', NS, '--replicas=0')
|
||||
k('wait', '--for=delete', 'pod', '-n', NS,
|
||||
'-l', 'app.kubernetes.io/instance=coulomb-social', '--timeout=120s')
|
||||
created = True
|
||||
k('create', '-f', '-', payload=body)
|
||||
k('wait', '--for=condition=Ready', 'pod/' + name, '-n', NS, '--timeout=120s')
|
||||
dump = k('exec', '-n', 'databases', primary, '-c', 'postgres', '--',
|
||||
'pg_dump', '-U', 'postgres', '-d', 'coulomb_social_db', '-Fc')
|
||||
if not dump.startswith(b'PGDMP'):
|
||||
raise Refused('invalid_pg_dump')
|
||||
private_write(dest / 'database.dump', dump)
|
||||
archive_code = ('import io,sys,tarfile; b=io.BytesIO(); '
|
||||
't=tarfile.open(fileobj=b,mode="w:gz"); '
|
||||
't.add("/snapshot",arcname="content"); '
|
||||
't.close();sys.stdout.buffer.write(b.getvalue())')
|
||||
content = k('exec', '-n', NS, name, '--', 'python', '-c', archive_code)
|
||||
private_write(dest / 'content.tar.gz', content)
|
||||
receipt.update(status='captured', writers_quiesced=True,
|
||||
database_sha256=hashlib.sha256(dump).hexdigest(),
|
||||
content_sha256=hashlib.sha256(content).hexdigest(),
|
||||
database_bytes=len(dump), content_bytes=len(content))
|
||||
finally:
|
||||
try:
|
||||
if created:
|
||||
k('delete', 'pod', name, '-n', NS, '--wait=true', '--timeout=120s')
|
||||
finally:
|
||||
if paused:
|
||||
k('scale', 'deployment/coulomb-social', '-n', NS, '--replicas=1')
|
||||
k('rollout', 'status', 'deployment/coulomb-social', '-n', NS, '--timeout=180s')
|
||||
receipt['app_resumed'] = True
|
||||
receipt['elapsed_seconds'] = round(time.monotonic() - started, 2)
|
||||
private_write(dest / 'receipt.json', json.dumps(receipt, indent=2).encode())
|
||||
print(json.dumps(receipt))
|
||||
return 0
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if '--execute' not in sys.argv:
|
||||
return snapshot()
|
||||
LOCK_PATH.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
|
||||
parent = LOCK_PATH.parent.lstat()
|
||||
if (not stat.S_ISDIR(parent.st_mode) or parent.st_uid != os.geteuid()
|
||||
or parent.st_mode & 0o077):
|
||||
raise Refused('lock_directory_not_private')
|
||||
fd = os.open(LOCK_PATH, os.O_CREAT | os.O_RDWR | os.O_NOFOLLOW, 0o600)
|
||||
with os.fdopen(fd, 'w') as lock:
|
||||
try:
|
||||
fcntl.flock(lock, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
except BlockingIOError:
|
||||
raise Refused('snapshot_already_running') from None
|
||||
def terminate(signum, frame):
|
||||
raise Refused('snapshot_interrupted')
|
||||
previous = signal.signal(signal.SIGTERM, terminate)
|
||||
try:
|
||||
return snapshot()
|
||||
finally:
|
||||
signal.signal(signal.SIGTERM, previous)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
sys.exit(main())
|
||||
except Exception as exc:
|
||||
# Never expose child output, kubectl objects, credentials or raw exception messages.
|
||||
print(json.dumps({'status': 'failed', 'failure_type': type(exc).__name__}))
|
||||
sys.exit(1)
|
||||
50
release/content-acceptance-values.yaml
Normal file
50
release/content-acceptance-values.yaml
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# Production overrides for coulomb-social.
|
||||
# Non-secret values only. Secrets live in K8s Secret coulomb-social-env.
|
||||
|
||||
image:
|
||||
repository: forgejo.coulomb.social/coulomb/coulomb-social
|
||||
tag: "1139a6d30eee"
|
||||
digest: "sha256:7906f461bc8d2d5204fd4fde67a251850f725b914452a66172919d6853672ed5"
|
||||
|
||||
# Public host: app.coulomb.social (parallel to Bubble on apex coulomb.social).
|
||||
# Apex cutover is deferred until data + self-registration are ready.
|
||||
env:
|
||||
DJANGO_SETTINGS_MODULE: coulomb_social.settings.prod
|
||||
ALLOWED_HOSTS: app.coulomb.social,localhost
|
||||
CSRF_TRUSTED_ORIGINS: https://app.coulomb.social
|
||||
CONTENT_ROOT: /app/var/content
|
||||
DEFAULT_TENANT_ID: "tenant:coulomb"
|
||||
OIDC_ENABLED: "true"
|
||||
OIDC_ISSUER: https://kc.coulomb.social
|
||||
OIDC_CLIENT_ID: coulomb-social
|
||||
OIDC_REDIRECT_URI: https://app.coulomb.social/auth/callback/
|
||||
OIDC_SCOPES: "openid profile email groups"
|
||||
USER_ENGINE_BASE_URL: https://users.coulomb.social
|
||||
USER_ENGINE_APPLICATION_ID: coulomb-social
|
||||
USER_ENGINE_EXPECTED_AUDIENCE: user-engine-portal
|
||||
NETKINGDOM_REGISTRATION_URL: https://users.92-205-62-239.nip.io/register
|
||||
|
||||
probes:
|
||||
hostHeader: app.coulomb.social
|
||||
path: /healthz
|
||||
|
||||
# One writable local-path volume; Recreate prevents concurrent old/new writers.
|
||||
replicaCount: 1
|
||||
deploymentStrategy: Recreate
|
||||
persistence:
|
||||
content:
|
||||
enabled: true
|
||||
storageClass: local-path
|
||||
size: 2Gi
|
||||
mountPath: /app/var/content
|
||||
retain: true
|
||||
|
||||
# Wave-2 right-sizing (CSOC-WP-0017-T01, 2026-10-21 node budget): 7d p95
|
||||
# 0.4m CPU / 146Mi. Limits stay at the chart defaults (1000m/1Gi).
|
||||
resources:
|
||||
requests:
|
||||
cpu: 15m
|
||||
memory: 176Mi
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 1Gi
|
||||
79
release/coulomb-content-acceptance-1139a6d.json
Normal file
79
release/coulomb-content-acceptance-1139a6d.json
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
{
|
||||
"schema": "coulomb.reviewed-image-release.v1",
|
||||
"proposal_id": "CSOC-CONTENT-ACCEPTANCE-20261031",
|
||||
"scope": "ADMINISTER @ realm:kubernetes/railiance01; supervised founder execution only",
|
||||
"operation": "image_only_existing_migration_0003",
|
||||
"cluster_uid": "a553c742-0115-43d4-99a4-a5ca56fe0786",
|
||||
"baseline_revision": 19,
|
||||
"baseline_helm_manifest_sha256": "93cb277abd1aea0657be482e458dcfb268fe0bfbd45d90aa1faedcc7f5bce499",
|
||||
"candidate_render_sha256": "680debbf4f35d9571916e2016c83327d1212665be82164c40d2d0a49081fc4a8",
|
||||
"deployment_uid": "2dbe661a-d232-4477-bbd1-833813077fbe",
|
||||
"pvc_uid": "9888abeb-9d52-4c70-a23d-b5494780d9c3",
|
||||
"baseline_spec_sha256": "42e091e52d5dae3c1f986e4898c62057fa80846adfce049a75d8fbd4681180ea",
|
||||
"candidate_spec_sha256": "8d79c64cff4bd2c62f03494e80847dc99b965ddabf35645da67e8d1020220798",
|
||||
"old_image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:522bcd7fce92436765a60c1e4afa2598f3cc40913352153ff1c4319a99ca92ed",
|
||||
"candidate_image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:7906f461bc8d2d5204fd4fde67a251850f725b914452a66172919d6853672ed5",
|
||||
"product_source": "1139a6d30eee4f75317b46bd45120a15d818455f",
|
||||
"expected_data": {
|
||||
"business_tables": 12,
|
||||
"migration_rows_sha256": "43471516387c0e2a3d35971033ed6af330e2963efe4da93293d97633825d04af",
|
||||
"business_rows": 93,
|
||||
"business_rows_sha256": "7953b37b02b80d89ca6869dab6b2b0b996541de20ca0dd1b294a5f25572fb2ca",
|
||||
"content_files": 86,
|
||||
"content_files_sha256": "ed535246f4e8f46fcd7ce01f936127996aff873c6936b297f7272194b594aeda",
|
||||
"global_slug_constraint": true,
|
||||
"tenant_slug_constraint": true,
|
||||
"migration_0003_applied": true,
|
||||
"duplicate_slug_groups": 0
|
||||
},
|
||||
"public_recipient": "age1qm30jk8q0cezey652dk2dhcr3d9vs528v6lg8mavl6d4q3e3vgnqmrmyy3",
|
||||
"installed_helper_hashes": {
|
||||
"/opt/coulomb-social-backup/paired-backup.py": "d161c742d1a6a182460a57d0a1719591ab58fc94006f55169ad3d74442a93630",
|
||||
"/opt/coulomb-social-backup/snapshot-content-and-db.py": "dcc8dd2a3989f279597595f9260b31b24fcc9b6dc787f04c17ef0491c53d830d",
|
||||
"/opt/coulomb-social-backup/mirror-paired-backup.py": "9ceb26d9083af016c4b787907e4dce7bdf437c782fb2d15eb28d9e334e6e431c",
|
||||
"/opt/coulomb-social-backup/check-paired-backup-health.py": "2d40ec6e4c59ea7fe1d46065d197b9a87ca6811f023cc6f3e20e4184a3490566",
|
||||
"/opt/coulomb-social-backup/backup_capacity.py": "cb699a79e67b129239b5aa5d6f3b0d4ffaa9773a8b073227ad17fdecb5b9d893",
|
||||
"/opt/railiance-platform/scripts/application_recovery_identities.py": "20f56255ed6eeec4aafe33f142bc3ee03f623d4957a7b0cabb741d340f15f79d",
|
||||
"/opt/railiance-platform/scripts/application_recovery_mirror.py": "d48ab95e89b9eeae36269d853ebe4c44c22e1f57d4e14224f03d0b9aeeb34178",
|
||||
"/opt/railiance-platform/scripts/application_recovery_resources.py": "ab70ec341e738272730eb0daf76840d0bca807caeb3c4e4c2357f162fbed4498",
|
||||
"/opt/railiance-platform/scripts/primary_application_archive.py": "a3f0a61e869a6012edb4b5288be14e3b0c4a9a1273b090320ab146d12e5aa94d",
|
||||
"/opt/coulomb-social-backup/backup_alerts.py": "07522437d4276b92f0a44149adc6c9e81bb18dbe59ce0f1f9e58a48347700d0e",
|
||||
"/opt/coulomb-social-backup/notify-backup-alert.py": "0bd53bc5ad22d8bcb0326fb18a17737744b06416fe785dad077308e45f051d5a",
|
||||
"/opt/coulomb-social-backup/observe-backup-alerts.py": "17caf4fa65283242f618b039ff1d018801c9890ea2a9178912cbdd4b50ee2664"
|
||||
},
|
||||
"clipboard_static_sha256": "347eabe0c8d93bf439df02b5a08a7ea71004600e6ff4e8a42cecbee52a9f0413",
|
||||
"fresh_backup_before_helm": true,
|
||||
"requires_dataset_equality_before_and_after": true,
|
||||
"node_request_percent_limit": 90,
|
||||
"helm_atomic_timeout_seconds": 300,
|
||||
"rollback": "Restore Helm revision19/image522bcd7f and verified snapshot pin; preserve all post-capture data. No production data restore or schema downgrade.",
|
||||
"approval_status": "prepared_not_admitted",
|
||||
"recovery_rehearsal_scope": "Candidate and previous image verified read-only against retained independently recovered 2026-10-31T07:13:52Z point: all13 tables/86 files unchanged,40 owner views/40 outsider denials,85 selected-client export files verified. Live baseline remains93 business rows versus92 at the retained point; previously verified session/login-only drift remains unchanged. Fresh paired capture/readback before Helm and independent recovery of that fresh point remain required.",
|
||||
"rehearsal_evidence_sha256": {
|
||||
"content-acceptance-build-2026-10-31.json": "39c5c78174e0dfc7fd93c4b718c2b15aa68cea8298be517e28ee2bd206912dd9",
|
||||
"content-acceptance-provenance-2026-10-31.json": "7d24b3eecf0c2c9c923812a318d448233f5bfc9ae4242046dae1c4d20e7e664a",
|
||||
"content-acceptance-tests-2026-10-31.json": "3da4d155d84553d7f2949d7e14e5c9cc6c819a6be6af04db5819b7f43ed18e47",
|
||||
"content-acceptance-recovery-2026-10-31.json": "4ec1b46d8076c42ac0e5bc106b7ff7debf25a65e6c02d907d7148c200a811ede",
|
||||
"content-acceptance-target-2026-10-31.json": "6651cbf0e2df889315464638158c3aaad885c3cb39fd5b51f06a5037434efebb",
|
||||
"attachment-menu-validation-2026-10-31.json": "7e491219c701d2e67bb2c3bc849af1fb1a58f787fd17e0527eefcf6345c62f2d",
|
||||
"ordered-list-fidelity-2026-10-31.json": "4dc3091876d355648d7482187d54f6a0501355274c263d0009d5d5ff6f42f64f",
|
||||
"content-lifecycle-validation-2026-10-31.json": "cbb093af470588ca6e8eb3ec5bc1ccee0be537ab37a46625b6ac267c17343d99",
|
||||
"content-lifecycle-baseline-tests-2026-10-31.json": "de14e4e10337990ccec1c483f7d943bdc7e11b03aa813aff47d00a9b38a07b65",
|
||||
"content-lifecycle-release-row-drift-2026-10-31.json": "b10f65bf55e900199ae6037767f32e8901aaccb6f7f3a86461f13dd02ec8efce",
|
||||
"backup-route-independent-return-2026-10-31.json": "3a3feb56c1af7e3db7b0f2380ec355bb465663073c0a0160034a35984ef23f6e",
|
||||
"backup-installation-independent-return-2026-10-31.json": "2fe1972f4db0ba2468027f4926cd8111d6aa4b61d404592eda794b47733ce0df"
|
||||
},
|
||||
"new_resources_committed": 0,
|
||||
"autopilot_or_eur_budget_claimed": false,
|
||||
"values_file": "release/content-acceptance-values.yaml",
|
||||
"snapshot_file": "release/content-acceptance-snapshot.py",
|
||||
"evidence_directory": "release/content-acceptance-evidence",
|
||||
"prerequisite_installation_digest": "sha256:8f442bf0ebed8bbf3b7f227b52081df52613f3f5f6874c4a59511cfc2ba06d42",
|
||||
"requires_inactive_backup_units": true,
|
||||
"product_changes": [
|
||||
"Preserve ordered-list start numbers",
|
||||
"Durable interrupted copy/move asset recovery",
|
||||
"Plain attachment menu: author upload/remove and authenticated reader downloads; revisioned associations and independent copies/moves"
|
||||
],
|
||||
"product_decision": "78175c34-58e1-4ad6-944d-0662c0462ae6"
|
||||
}
|
||||
|
|
@ -424,15 +424,15 @@ coulomb-social/docs/release/backup-producer-custody-validation-2026-10-31.json.
|
|||
The historical eight-entry repair and recurring service acceptance remain product
|
||||
T04/T09. No cluster operation occurred; future release proposals bind the new source.
|
||||
|
||||
## T07 — Deliver the attachment crash-recovery correction
|
||||
## T07 — Deliver the combined content and author attachment release
|
||||
|
||||
```task
|
||||
id: RAPPS-WP-0015-T07
|
||||
status: wait
|
||||
priority: high
|
||||
needs_human: false
|
||||
wait_kind: external
|
||||
blocking_reason: "Prepared image packet c9c32316 waits for CSOC-WP-0012-T08 inactive installation8f442bf0; native preflight confirms its receipt is absent."
|
||||
needs_human: true
|
||||
wait_kind: human
|
||||
blocking_reason: "Combined packet e96752ec passes full native preflight after independently verified inactive installation8f442bf0; founder-terminal execution and independent return remain required."
|
||||
depends_on:
|
||||
- CSOC-WP-0012-T08
|
||||
state_hub_task_id: "8f448934-bdfe-539f-8cab-a739ec752491"
|
||||
|
|
@ -482,3 +482,25 @@ coulomb-social/docs/usecases/sharing-portability-review.md, lifecycle release se
|
|||
Evidence: content-lifecycle-release-{target,row-drift,preflight,proposal,preparation}
|
||||
JSON files in the consumer docs/release directory. T07 is now external wait for T08;
|
||||
product policy is settled, and productive lifecycle acceptance remains open.
|
||||
|
||||
|
||||
2026-10-31 combined candidate: the route and inactive installation now have
|
||||
founder-executed independent returns. User requested plain attachment actions,
|
||||
including author add/remove (product decision78175c34), and accepted the three
|
||||
custom-topic rendering cases for now. The new source1139a6d combines the original
|
||||
crash-recovery correction, ordered-list starts and revisioned attachment actions.
|
||||
Image7906f461 has exact packaged provenance and unchanged runtime dependencies;
|
||||
no schema migration. Main gate670, isolated source gate568 and packaged110 pass.
|
||||
The retained independently recovered pair remains unchanged across candidate/old
|
||||
40owner/40outsider views and85file selected-client export, all13tables/86files.
|
||||
|
||||
New immutable plan: release/coulomb-content-acceptance-1139a6d.json.
|
||||
Exact proposal: sha256:e96752ecfa7adef2fd1d9da48902c8e63de124ccfd272fe20ba79b758b3ca4a3.
|
||||
Full native read-only preflight passes at revision19 with unchanged93business
|
||||
rows/86files, complete desired specification, Helm/server previews, installed
|
||||
source prerequisite and inactive units. Historical c9c32316 remains unchanged;
|
||||
use the new combined proposal only. Founder-terminal execution remains required.
|
||||
The reviewed action captures a fresh pair before atomic Helm rollout and refreshes
|
||||
the snapshot image pin after unchanged-data/view checks. No timer activation,
|
||||
production restore, purge or mail. Productive acceptance remains with WP-0013.
|
||||
Review/command: coulomb-social/docs/release/content-acceptance-review-2026-10-31.md.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue