From 979b7819df469a052021ccfa64ddbbc4eb640e12 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 31 Oct 2026 22:16:46 +0100 Subject: [PATCH] Prepare attended Coulomb editor attachment visibility release Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a192e9-c28b-7533-bf25-e2341364c22a --- WORK-RECORDS.md | 1 + .../coulomb-editor-attachments-31eaa58.json | 77 ++++ ...llation-independent-return-2026-10-31.json | 371 ++++++++++++++++++ ...p-route-independent-return-2026-10-31.json | 29 ++ ...nce-independent-postflight-2026-10-31.json | 41 ++ ...ttachments-baseline-change-2026-10-31.json | 39 ++ .../editor-attachments-build-2026-10-31.json | 45 +++ ...tor-attachments-provenance-2026-10-31.json | 11 + ...ditor-attachments-recovery-2026-10-31.json | 67 ++++ .../editor-attachments-target-2026-10-31.json | 21 + .../editor-attachments-tests-2026-10-31.json | 13 + ...tor-attachments-validation-2026-10-31.json | 34 ++ release/editor-attachments-snapshot.py | 175 +++++++++ release/editor-attachments-values.yaml | 50 +++ ...P-0015-coulomb-personal-content-release.md | 28 ++ 15 files changed, 1002 insertions(+) create mode 100644 release/coulomb-editor-attachments-31eaa58.json create mode 100644 release/editor-attachments-evidence/backup-installation-independent-return-2026-10-31.json create mode 100644 release/editor-attachments-evidence/backup-route-independent-return-2026-10-31.json create mode 100644 release/editor-attachments-evidence/content-acceptance-independent-postflight-2026-10-31.json create mode 100644 release/editor-attachments-evidence/editor-attachments-baseline-change-2026-10-31.json create mode 100644 release/editor-attachments-evidence/editor-attachments-build-2026-10-31.json create mode 100644 release/editor-attachments-evidence/editor-attachments-provenance-2026-10-31.json create mode 100644 release/editor-attachments-evidence/editor-attachments-recovery-2026-10-31.json create mode 100644 release/editor-attachments-evidence/editor-attachments-target-2026-10-31.json create mode 100644 release/editor-attachments-evidence/editor-attachments-tests-2026-10-31.json create mode 100644 release/editor-attachments-evidence/editor-attachments-validation-2026-10-31.json create mode 100644 release/editor-attachments-snapshot.py create mode 100644 release/editor-attachments-values.yaml diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index ffb3b14..dd00903 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -44,6 +44,7 @@ | task | RAPPS-WP-0015-T05 | done | — | workplans/RAPPS-WP-0015-coulomb-personal-content-release.md | | task | RAPPS-WP-0015-T06 | done | — | workplans/RAPPS-WP-0015-coulomb-personal-content-release.md | | task | RAPPS-WP-0015-T07 | done | — | workplans/RAPPS-WP-0015-coulomb-personal-content-release.md | +| task | RAPPS-WP-0015-T08 | wait | — | workplans/RAPPS-WP-0015-coulomb-personal-content-release.md | | task | RAPPS-WP-0016-T01 | done | — | workplans/RAPPS-WP-0016-forgejo-netkingdom-login.md | | task | RAPPS-WP-0016-T02 | wait | — | workplans/RAPPS-WP-0016-forgejo-netkingdom-login.md | | task | RAPPS-WP-0016-T03 | wait | — | workplans/RAPPS-WP-0016-forgejo-netkingdom-login.md | diff --git a/release/coulomb-editor-attachments-31eaa58.json b/release/coulomb-editor-attachments-31eaa58.json new file mode 100644 index 0000000..bf8cddf --- /dev/null +++ b/release/coulomb-editor-attachments-31eaa58.json @@ -0,0 +1,77 @@ +{ + "schema": "coulomb.reviewed-image-release.v1", + "proposal_id": "CSOC-EDITOR-ATTACHMENTS-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": 20, + "baseline_helm_manifest_sha256": "e388f62c97e97d54d87671825bd0b05c854a70b0cca8a00faee452ae7841799e", + "candidate_render_sha256": "78ee8e0a73f87e1152b6f826029ed85385b6293c61a1cdab7171b6c6e40580bc", + "deployment_uid": "2dbe661a-d232-4477-bbd1-833813077fbe", + "pvc_uid": "9888abeb-9d52-4c70-a23d-b5494780d9c3", + "baseline_spec_sha256": "8d79c64cff4bd2c62f03494e80847dc99b965ddabf35645da67e8d1020220798", + "candidate_spec_sha256": "4deab26fc15d63e09922259b3362cd4e5c6bfa10884de058f776c0de8b642b00", + "old_image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:7906f461bc8d2d5204fd4fde67a251850f725b914452a66172919d6853672ed5", + "candidate_image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:b58d858abd5b4acbd6b893c3f622f7a9fdb5e606164ab9866eb3cfaa04df1a0e", + "product_source": "31eaa581a65e454b6ef9979326c5bdfe10e13806", + "expected_data": { + "business_tables": 12, + "migration_rows_sha256": "43471516387c0e2a3d35971033ed6af330e2963efe4da93293d97633825d04af", + "business_rows": 97, + "business_rows_sha256": "35b0ae7d9dd1ff21c2ceaa04649162545ec36a2c68629548238352d9cd0fb303", + "content_files": 98, + "content_files_sha256": "b657c0e470399b6c7500da500cbbec061bea12ab9633bd74e2f142d797b2d26a", + "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": "23f92c96b840df61f92858004241e860e0ddb32ed6fd7448294d3c8278906e46", + "/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 revision20/image7906f461 and verified snapshot pin, preserving all data; no production restore or schema downgrade.", + "approval_status": "prepared_not_admitted", + "recovery_rehearsal_scope": "Candidate and previous image verified against independently recovered 2026-10-31T20:21:01Z point:13tables/86files unchanged,40owner views/40outsider denials,85export files verified. Current97-row/98-file baseline adds2spaces/2memberships/12files from productive acceptance; all prior rows and86files are unchanged. Fresh paired capture/readback before Helm and independent recovery afterward remain required.", + "rehearsal_evidence_sha256": { + "editor-attachments-build-2026-10-31.json": "bb58b2fe23d101ab82ee0b210cc8f552f3667c785bd0207b1e1656b0577c106d", + "editor-attachments-provenance-2026-10-31.json": "3d4ec97702c5165af2198da4c4563cba204355480f5036fd22c48b9e3c300ba3", + "editor-attachments-tests-2026-10-31.json": "59d2d121befa7a8c3853fc89172bad5ce2abad1c1615cc2f2bea550f4d68a62d", + "editor-attachments-recovery-2026-10-31.json": "af68f6e86c0b3291d4ad880717c36eb95f1592f78d3c65596dd9cecd10755052", + "editor-attachments-target-2026-10-31.json": "b6d767ecb93b4638ca77a5052dcf3aab8a95dee922d3927956ad578290f9e58f", + "editor-attachments-baseline-change-2026-10-31.json": "db79f2838b88281c562b36996e74694c2a98e113c962b46eab0ef2cf69dd3b8c", + "editor-attachments-validation-2026-10-31.json": "427e228a9f2763cd583496d65e21b7599ef5e0df074dc507277ce2051169f562", + "backup-route-independent-return-2026-10-31.json": "3a3feb56c1af7e3db7b0f2380ec355bb465663073c0a0160034a35984ef23f6e", + "backup-installation-independent-return-2026-10-31.json": "2fe1972f4db0ba2468027f4926cd8111d6aa4b61d404592eda794b47733ce0df", + "content-acceptance-independent-postflight-2026-10-31.json": "6a8a4056b143011c50af24dd31d6338d00892bfe626666f85e607d86562dfe7c" + }, + "new_resources_committed": 0, + "autopilot_or_eur_budget_claimed": false, + "values_file": "release/editor-attachments-values.yaml", + "snapshot_file": "release/editor-attachments-snapshot.py", + "evidence_directory": "release/editor-attachments-evidence", + "prerequisite_installation_digest": "sha256:8f442bf0ebed8bbf3b7f227b52081df52613f3f5f6874c4a59511cfc2ba06d42", + "requires_inactive_backup_units": true, + "product_changes": [ + "Show saved attachments and downloads in editor tabs", + "Keep attachment list and submitted text after stale edit refusal", + "Open attachment management in a separate tab to preserve unsaved editor text" + ], + "product_decision": "Productive review feedback: attachments present on original but absent from editing tabs." +} diff --git a/release/editor-attachments-evidence/backup-installation-independent-return-2026-10-31.json b/release/editor-attachments-evidence/backup-installation-independent-return-2026-10-31.json new file mode 100644 index 0000000..8417e00 --- /dev/null +++ b/release/editor-attachments-evidence/backup-installation-independent-return-2026-10-31.json @@ -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 +} diff --git a/release/editor-attachments-evidence/backup-route-independent-return-2026-10-31.json b/release/editor-attachments-evidence/backup-route-independent-return-2026-10-31.json new file mode 100644 index 0000000..fb0a51f --- /dev/null +++ b/release/editor-attachments-evidence/backup-route-independent-return-2026-10-31.json @@ -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 +} diff --git a/release/editor-attachments-evidence/content-acceptance-independent-postflight-2026-10-31.json b/release/editor-attachments-evidence/content-acceptance-independent-postflight-2026-10-31.json new file mode 100644 index 0000000..cdbc019 --- /dev/null +++ b/release/editor-attachments-evidence/content-acceptance-independent-postflight-2026-10-31.json @@ -0,0 +1,41 @@ +{ + "schema": "coulomb.content-acceptance-independent-postflight.v1", + "status": "deployed_image_and_complete_native_state_verified", + "proposal_digest": "sha256:e96752ecfa7adef2fd1d9da48902c8e63de124ccfd272fe20ba79b758b3ca4a3", + "receipt_sha256": "074ec03d62d43f35bd6c276213a28de4a7b0161132379221bec0e402b5334233", + "helm_revision": 20, + "image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:7906f461bc8d2d5204fd4fde67a251850f725b914452a66172919d6853672ed5", + "source": "1139a6d30eee4f75317b46bd45120a15d818455f", + "packaged_source_files_verified": 79, + "sole_ready_content_writer": true, + "all_frozen_capsule_files_verified": 23, + "installed_helper_hashes_verified": true, + "snapshot_pin_refreshed": true, + "public_health_landing_static_verified": true, + "postflight": { + "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, + "actual_owner_pages_rendered": 40, + "unsaved_outsider_page_denials": 40, + "production_identity_or_grant_created": false + }, + "fresh_paired_point": { + "captured_at": "2026-10-31T20:21:01Z", + "destination": "s3://railiance-platform-pg-backup/platform-pg/application-archives/coulomb-social/2026/10/31/20261031T202101Z-2ad4faf215939d67e82f67a4.tar.age", + "version_id": "1793478121590106", + "encrypted_sha256": "91b4ffe4874a53e3422d604b7c3fa85f6551a481411ef82b2209993552486bfb", + "encrypted_bytes": 2181848, + "image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:522bcd7fce92436765a60c1e4afa2598f3cc40913352153ff1c4319a99ca92ed" + }, + "timers_activated": false, + "production_data_restored": false, + "productive_acceptance_inferred": false +} diff --git a/release/editor-attachments-evidence/editor-attachments-baseline-change-2026-10-31.json b/release/editor-attachments-evidence/editor-attachments-baseline-change-2026-10-31.json new file mode 100644 index 0000000..71dc2f7 --- /dev/null +++ b/release/editor-attachments-evidence/editor-attachments-baseline-change-2026-10-31.json @@ -0,0 +1,39 @@ +{ + "schema": "coulomb.acceptance-baseline-change.v1", + "retained_point": "2026-10-31T20:21:01Z", + "old_business_rows": 93, + "new_business_rows": 97, + "table_changes": { + "spaces_space": { + "old": 2, + "new": 4, + "removed": 0, + "added": 2 + }, + "spaces_spacemembership": { + "old": 1, + "new": 3, + "removed": 0, + "added": 2 + } + }, + "old_content_files": 86, + "new_content_files": 98, + "old_files_missing": 0, + "old_files_changed": 0, + "new_files_added": 12, + "old_rows_preserved": true, + "current_baseline": { + "business_tables": 12, + "migration_rows_sha256": "43471516387c0e2a3d35971033ed6af330e2963efe4da93293d97633825d04af", + "business_rows": 97, + "business_rows_sha256": "35b0ae7d9dd1ff21c2ceaa04649162545ec36a2c68629548238352d9cd0fb303", + "content_files": 98, + "content_files_sha256": "b657c0e470399b6c7500da500cbbec061bea12ab9633bd74e2f142d797b2d26a", + "global_slug_constraint": true, + "tenant_slug_constraint": true, + "migration_0003_applied": true, + "duplicate_slug_groups": 0 + }, + "interpretation": "Changes observed during the user-requested productive acceptance session; no user verdict inferred." +} diff --git a/release/editor-attachments-evidence/editor-attachments-build-2026-10-31.json b/release/editor-attachments-evidence/editor-attachments-build-2026-10-31.json new file mode 100644 index 0000000..30efe22 --- /dev/null +++ b/release/editor-attachments-evidence/editor-attachments-build-2026-10-31.json @@ -0,0 +1,45 @@ +{ + "schema": "coulomb.content-acceptance-build.v1", + "completed_at": "2026-10-31T21:13:04.039838+00:00", + "source": "31eaa581a65e454b6ef9979326c5bdfe10e13806", + "image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:b58d858abd5b4acbd6b893c3f622f7a9fdb5e606164ab9866eb3cfaa04df1a0e", + "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 +} diff --git a/release/editor-attachments-evidence/editor-attachments-provenance-2026-10-31.json b/release/editor-attachments-evidence/editor-attachments-provenance-2026-10-31.json new file mode 100644 index 0000000..df09c4b --- /dev/null +++ b/release/editor-attachments-evidence/editor-attachments-provenance-2026-10-31.json @@ -0,0 +1,11 @@ +{ + "schema": "coulomb.packaged-source-provenance.v1", + "image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:b58d858abd5b4acbd6b893c3f622f7a9fdb5e606164ab9866eb3cfaa04df1a0e", + "source": "31eaa581a65e454b6ef9979326c5bdfe10e13806", + "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": "99401a60fdd9a95aff1168858e81fd7d8802cd7603f15c0ea35eb6917981f9fe" +} diff --git a/release/editor-attachments-evidence/editor-attachments-recovery-2026-10-31.json b/release/editor-attachments-evidence/editor-attachments-recovery-2026-10-31.json new file mode 100644 index 0000000..1623bcb --- /dev/null +++ b/release/editor-attachments-evidence/editor-attachments-recovery-2026-10-31.json @@ -0,0 +1,67 @@ +{ + "schema": "coulomb.packaged-content-acceptance-recovery.v1", + "status": "packaged_recovered_export_and_views_verified", + "source": "31eaa581a65e454b6ef9979326c5bdfe10e13806", + "image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:b58d858abd5b4acbd6b893c3f622f7a9fdb5e606164ab9866eb3cfaa04df1a0e", + "restore_receipt_sha256": "9dacbd44544f93abf99354158cf610b4fb1f4e59611b22056b3086e0033231ab", + "retained_point_captured_at": "2026-10-31T20:21:01Z", + "candidate_application": { + "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, + "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": 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, + "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": "ecf5dba7ce891475cd5df15eb30205606f805850af7339ecd46e1479b45d6c5f", + "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": "29c53d551eec2b4f4d60b047f123c727eef76ee7677c054bbfb0ab008355cff9" +} diff --git a/release/editor-attachments-evidence/editor-attachments-target-2026-10-31.json b/release/editor-attachments-evidence/editor-attachments-target-2026-10-31.json new file mode 100644 index 0000000..023ddde --- /dev/null +++ b/release/editor-attachments-evidence/editor-attachments-target-2026-10-31.json @@ -0,0 +1,21 @@ +{ + "baseline_revision": 20, + "baseline_helm_manifest_sha256": "e388f62c97e97d54d87671825bd0b05c854a70b0cca8a00faee452ae7841799e", + "deployment_uid": "2dbe661a-d232-4477-bbd1-833813077fbe", + "baseline_spec_sha256": "8d79c64cff4bd2c62f03494e80847dc99b965ddabf35645da67e8d1020220798", + "candidate_spec_sha256": "4deab26fc15d63e09922259b3362cd4e5c6bfa10884de058f776c0de8b642b00", + "old_image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:7906f461bc8d2d5204fd4fde67a251850f725b914452a66172919d6853672ed5", + "expected_data": { + "business_tables": 12, + "migration_rows_sha256": "43471516387c0e2a3d35971033ed6af330e2963efe4da93293d97633825d04af", + "business_rows": 97, + "business_rows_sha256": "35b0ae7d9dd1ff21c2ceaa04649162545ec36a2c68629548238352d9cd0fb303", + "content_files": 98, + "content_files_sha256": "b657c0e470399b6c7500da500cbbec061bea12ab9633bd74e2f142d797b2d26a", + "global_slug_constraint": true, + "tenant_slug_constraint": true, + "migration_0003_applied": true, + "duplicate_slug_groups": 0 + }, + "image_only_server_preview": true +} diff --git a/release/editor-attachments-evidence/editor-attachments-tests-2026-10-31.json b/release/editor-attachments-evidence/editor-attachments-tests-2026-10-31.json new file mode 100644 index 0000000..3570551 --- /dev/null +++ b/release/editor-attachments-evidence/editor-attachments-tests-2026-10-31.json @@ -0,0 +1,13 @@ +{ + "schema": "coulomb.packaged-content-acceptance-tests.v1", + "image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:b58d858abd5b4acbd6b893c3f622f7a9fdb5e606164ab9866eb3cfaa04df1a0e", + "source": "31eaa581a65e454b6ef9979326c5bdfe10e13806", + "tests": 110, + "failures": 0, + "errors": 0, + "skipped": 0, + "network": "none", + "read_only_root": true, + "application_source_overlay": false, + "synthetic_fixtures_only": true +} diff --git a/release/editor-attachments-evidence/editor-attachments-validation-2026-10-31.json b/release/editor-attachments-evidence/editor-attachments-validation-2026-10-31.json new file mode 100644 index 0000000..23e9b42 --- /dev/null +++ b/release/editor-attachments-evidence/editor-attachments-validation-2026-10-31.json @@ -0,0 +1,34 @@ +{ + "schema": "coulomb.editor-attachments-validation.v1", + "reported_gap": "Attachments visible on the original page were absent from editor tabs.", + "main_source": "8b38afddf3f3648f209c60b1bafe3dd25501d857", + "release_source": "31eaa581a65e454b6ef9979326c5bdfe10e13806", + "image": "forgejo.coulomb.social/coulomb/coulomb-social@sha256:b58d858abd5b4acbd6b893c3f622f7a9fdb5e606164ab9866eb3cfaa04df1a0e", + "main_full_gate": { + "tests": 670, + "failures": 0, + "errors": 0, + "skipped": 0 + }, + "release_full_gate": { + "tests": 568, + "failures": 0, + "errors": 0, + "skipped": 0 + }, + "packaged_tests": 110, + "browser_verifies": [ + "saved file list and exact download bytes in both editor tabs", + "management opens separately and keeps unsaved text", + "stale refusal keeps submitted text and attachments", + "save keeps attachments and rejects stale overwrite", + "existing copy/move/download/detach permissions journey" + ], + "runtime_changes": [ + "coulomb_social/apps/spaces/views.py", + "coulomb_social/templates/spaces/page_form.html" + ], + "storage_schema_or_authority_changed": false, + "productive_acceptance_inferred": false, + "test_environment": "Main uses /var/tmp; isolated branch native observer requires /tmp. Final complete gates pass without deselection." +} diff --git a/release/editor-attachments-snapshot.py b/release/editor-attachments-snapshot.py new file mode 100644 index 0000000..342510b --- /dev/null +++ b/release/editor-attachments-snapshot.py @@ -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:' + 'b58d858abd5b4acbd6b893c3f622f7a9fdb5e606164ab9866eb3cfaa04df1a0e') +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) diff --git a/release/editor-attachments-values.yaml b/release/editor-attachments-values.yaml new file mode 100644 index 0000000..9e85e9b --- /dev/null +++ b/release/editor-attachments-values.yaml @@ -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: "31eaa581a65e" + digest: "sha256:b58d858abd5b4acbd6b893c3f622f7a9fdb5e606164ab9866eb3cfaa04df1a0e" + +# 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 diff --git a/workplans/RAPPS-WP-0015-coulomb-personal-content-release.md b/workplans/RAPPS-WP-0015-coulomb-personal-content-release.md index 7682515..3a151d4 100644 --- a/workplans/RAPPS-WP-0015-coulomb-personal-content-release.md +++ b/workplans/RAPPS-WP-0015-coulomb-personal-content-release.md @@ -518,3 +518,31 @@ pass40owner/40outsider checks; client export verifies85files with all source SQL/files unchanged. Owner live values and consumer source/helper pins now match revision20. Recovery remains isolated; timers are inactive/disabled. Remaining user workflow verdicts are tracked by existing CSOC-WP-0013-T02/T03/T05/T06. + +## T08 — Deliver the editor attachment visibility correction + +```task +id: RAPPS-WP-0015-T08 +status: wait +priority: high +needs_human: true +wait_kind: human +decision_id: "0d538348-aadd-41a2-88f6-191defcf22b2" +blocking_reason: "Exact editor attachment proposal2cddcf38 passes native preflight; founder-terminal execution and independent return are required." +``` + +Productive revision20 review identified that attachments are visible on the +original page but absent from editor tabs. CSOC-WP-0013-T06 owns the correction: +display saved attachments/downloads in the editor and preserve that list after +stale-edit refusal, with management opening separately to retain unsaved text. +Prepare the minimal follow-up image from the deployed source, preserve existing +schema/data/permissions, and reuse the exact attended image-release lane with a +fresh paired rollback point. Complete after founder execution and independent +postflight/recovery/source-pin reconciliation. Productive acceptance remains +CSOC-WP-0013-T03/T06; T07's verified revision20 delivery stays complete. + +Prepared source31eaa58/imageb58d858a; exact proposal2cddcf38b7052287c10dce467a200a74cfa9699c666ae9ac538fc82917129e7a. Main670/isolated568/packaged110 pass. +Recovered views/export pass. Full native preflight at revision20/97rows/98files +passes; existing93rows/86files are unchanged by the productive review additions. +Plan: release/coulomb-editor-attachments-31eaa58.json. Review/command: +coulomb-social/docs/release/content-acceptance-review-2026-10-31.md.