Record populated pilot capture and prepare encrypted export
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a1abf1-7e95-7141-87c9-ee78332bf790
This commit is contained in:
tegwick 2026-11-06 01:02:59 +01:00
parent 8fd2c9772d
commit d2e1377354
11 changed files with 713 additions and 8 deletions

View file

@ -0,0 +1,29 @@
{
"schema": "railiance.vergabe-pilot-user-return.v1",
"reported_on": "2026-11-06",
"workplan": "RAPPS-WP-0014",
"task": "RAPPS-WP-0014-T03",
"run_id": "20261105T233543Z-89bfbe04dece",
"evidence_kind": "user_reported",
"two_accounts_work_after_restart": true,
"user_report": "Both accounts work. The Ausschreibung is no longer listed on the \u00dcbersicht; everything else seems as before.",
"human_restart_check": "confirmed_with_overview_followup",
"overview_omission_reported": true,
"overview_followup": {
"deployed_source_revision": "c067993037f1cdeeb7b22d5600b51c649bc239db",
"source_file": "vergabe_teilnahme/apps/ausschreibungen/views.py",
"function": "dashboard",
"ongoing_list_filter": "status__range=(1, 9); latest ten by geaendert_am",
"final_statuses_omitted": [
10,
11,
12,
13
],
"fixture_current_status": "not_reported; clarification requested",
"explanation": "A final status would explain exclusion; phase 8 alone is included. No live status or data-loss cause is inferred."
},
"provider_publication_verified": false,
"restore_verified": false,
"authentication_policy_changed": false
}

View file

@ -0,0 +1,44 @@
{
"schema": "railiance.vergabe-pilot-three-store-capture.v1",
"run_id": "20261105T233543Z-89bfbe04dece",
"status": "captured_and_resumed",
"database": "vergabe_demo_company",
"helm_revision": 4,
"app_resumed": true,
"off_host_verified": false,
"restore_verified": false,
"media_files": 1,
"media_bytes": 803,
"media_logical_sha256": "24fe90da88973ac03c8a475dff93c5866cebd797aeecdca2286989a1250779ed",
"fixture_document_sha256": "23a6850fa2391a58280c8515361ca29e9e92fa65fdadc36be7b44b552192e381",
"sqlite": {
"tables": 9,
"rows": 7,
"logical_sha256": "579dedb0e6a6b30f6cf3a5cec27ae423dbdaf0de959837cb9d697f6d5a789258",
"linked_issue_found": true,
"integrity_verified": true
},
"stores_sha256": "6affa22da26badb4daceb87acf62d4eba57bfbfc2d60da0823b607c449596d66",
"stores_bytes": 3489,
"database_sha256": "8758ebd2e2b6c9e75742c42f2d32f71596522f5aade3a7212ed5a04c3cf3476c",
"database_bytes": 169232,
"database_tables": 39,
"database_rows": 247,
"database_logical_sha256": "33191c43c437f1b05da410a3f22989c86ce50f4fca8fd32d40fbb327b8b73765",
"writers_quiesced": true,
"anonymous_document_http_status": 302,
"anonymous_document_denied": true,
"helper_cleanup_confirmed": true,
"restart_fixture_verified": true,
"elapsed_seconds": 98.61,
"evidence_kind": "user_reported_terminal_output",
"reported_on": "2026-11-06",
"workplan": "RAPPS-WP-0014",
"task": "RAPPS-WP-0014-T03",
"command": "python3 tools/vergabe_pilot_snapshot_remote.py --execute",
"founder_executed_reviewed_change": true,
"elapsed_seconds_scope": "Whole helper operation after preflight; not separately measured outage duration",
"human_two_account_post_restart_walkthrough": "confirmed_with_overview_followup",
"production_data_restored": false,
"human_return_receipt": "2026-11-06-vergabe-post-restart-user-return.json"
}

View file

@ -0,0 +1,85 @@
# Export the populated Vergabe recovery point
The founder's [native capture receipt](../../evidence/2026-11-06-vergabe-three-store-capture-return.json)
passes for run `20261105T233543Z-89bfbe04dece`. The app has resumed and both
accounts work, with the [overview UI follow-up](../../evidence/2026-11-06-vergabe-post-restart-user-return.json).
This step transfers the frozen point; it needs no further application pause.
[Exact scope, pins and validation](plan.json).
## Founder workstation command
```bash
git pull --ff-only
python3 tools/vergabe_pilot_export_remote.py --fetch
```
Default without `--fetch` reviews locally. `--fetch` uses the same existing
interactive SSH/sudo lane as inventory and capture. The agent does not execute
the founder's credential path. No remote checkout is needed.
The node helper requires the successful capture receipt and the exact database
and stores sizes/hashes from the returned receipt. It packages only
`database.dump`, `stores.tar.gz`, `manifest.private.json`, `receipt.json` and a
generated packet manifest. Raw SQLite copies/work directories are excluded.
Using the existing platform **public** age recipient, it encrypts on railiance01
and retains the encrypted point plus its hash manifest in the root-private run
directory. A temporary plaintext package exists only inside that protected
directory and is removed after sealing. The original capture is preserved.
An interrupted, inconsistent seal stops for review rather than being overwritten.
The helper copies ciphertext and safe transfer metadata to two 0600 files in
the existing founder SSH account's home (`tegwick`), named
`vergabe-pilot-20261105T233543Z-89bfbe04dece.{zip.age,transfer.json}`.
Only those encrypted handoff files are made readable by that account; the
private capture files remain root-only. Existing different handoff bytes refuse.
The wrapper uses scp to fetch the pair into a private temporary directory, then
checks the source run/image/database, captured database/store hashes, encrypted
size and ciphertext hash. Only a verified pair becomes the final directory:
```text
~/.local/state/vergabe-pilot-recovery/20261105T233543Z-89bfbe04dece/
```
It refuses a destination inside a Git tree. Files are 0600 and the directory is
0700. An already verified pair can be reused on retry. Successful final JSON
has `status: encrypted_workstation_copy_verified` and includes the local path.
Return that JSON, without opening or pasting backup contents.
No Kubernetes/database access, application change, OpenBao access, provider call
or recovery-key retrieval occurs. Age must already be available on the node at
one of the standard or existing platform vendor paths. Missing age fails before
sealing; this command does not install tools or alter the platform configuration.
## What this establishes
The encrypted bytes are now copied to the founder's workstation outside the
production node, with transport hashes verified. This is a separate milestone
from publication to the declared backup provider. The receipt keeps
`provider_publication_verified`, `decryption_verified` and `restore_verified`
false. Public-key encryption alone does not prove the escrow identity can recover
the point, and no recurring protection or accepted recovery objective is inferred.
Credential routing confirms the existing `railiance-backup-offsite-lane` belongs
to railiance-platform. Its Nextcloud file-drop credential is create-only;
independent readback uses the Backup account, and age decryption uses recovery
escrow in a contained founder login. Reuse those owner helpers for publication
and readback; do not borrow another application's Scaleway publisher identity.
No new credential lane, role, provider folder, retention change or timer is
created by this export. The upload-only token is not readback authority.
After provider readback, rehearse an isolated restore of this matched point with
outgoing integrations disabled. Verify every PostgreSQL table digest, documents
and local issue linkage, restored account behavior, source/image availability and
elapsed recovery time. Compatible rollback, access denial and named backup/support
ownership, cadence, retention and accepted RPO/RTO remain T03 requirements.
## Validation
`python3 -m unittest discover -s tests -p test_vergabe_pilot_export.py`: seven
synthetic checks pass. They include actual age encryption/decryption, complete
packet comparison, changed capture/ciphertext rejection, unsafe source refusal,
handoff preservation, verified transfer/retry and Git destination refusal.
No native backup or real key is read by those tests. Native export remains
founder-executed and unverified until its receipt returns.

View file

@ -0,0 +1,49 @@
{
"schema": "railiance.vergabe-pilot-recovery-export-plan.v1",
"prepared_on": "2026-11-06",
"workplan": "RAPPS-WP-0014",
"task": "RAPPS-WP-0014-T03",
"run_id": "20261105T233543Z-89bfbe04dece",
"sources": {
"vergabe_pilot_recovery_store": "724a2dd9db8a0f57e1efa709ec989d8a47c681a86b1fca923bfdfea1698ae23c",
"vergabe_pilot_export": "b45733fa10ae59b56563045c43c53b5f824a74e1114f68fbed28404f14b43e3a"
},
"execution": "Founder workstation --fetch: interactive SSH/sudo on railiance01, followed by scp of ciphertext and a safe manifest",
"source": "/var/lib/vergabe-pilot-recovery/20261105T233543Z-89bfbe04dece/",
"scope": [
"Verify accepted capture receipt and pinned database/stores byte sizes and SHA256",
"Package only database.dump, stores.tar.gz, manifest.private.json, receipt.json and generated packet.json",
"Encrypt on the node to the existing platform public age recipient",
"Create mode-0600 encrypted handoff files for the existing founder SSH account",
"Copy and checksum-verify ciphertext and transfer metadata in a private workstation directory outside Git"
],
"recipient": "age1zvryunvjhvpkmasskauga2heeg0ztnte9ymgppvjge36ekumk50syr3tsz",
"recipient_source": "railiance-platform/lib/railiance-backup-common.sh",
"node_ciphertext": "recovery-point.zip.age",
"node_public_manifest": "seal.json",
"founder_handoff_basename": "vergabe-pilot-20261105T233543Z-89bfbe04dece",
"workstation_directory": "~/.local/state/vergabe-pilot-recovery/20261105T233543Z-89bfbe04dece/",
"application_mutations": false,
"database_access": false,
"secret_reads": false,
"openbao_access": false,
"provider_access": false,
"provider_publication_verified": false,
"decryption_verified": false,
"restore_verified": false,
"next_provider_route": {
"id": "railiance-backup-offsite-lane",
"owner_repo": "railiance-platform",
"provider": "Existing Nextcloud create-only file-drop lane; independent Backup account for readback; age escrow for contained decrypt verification",
"route_only_not_publication_evidence": true
},
"validation": {
"unit_cases_passed": 7,
"actual_age_synthetic_round_trip": true,
"tampered_capture_or_ciphertext_refused": true,
"existing_handoff_not_overwritten": true,
"transport_retry_uses_verified_pair": true,
"git_destination_refused": true,
"native_export_executed": false
}
}

View file

@ -37,6 +37,14 @@ data. A failed check stops before any capture mutation.
## Prepared capture, after the founder's go
Executed by the founder: run `20261105T233543Z-89bfbe04dece` reports
[`captured_and_resumed`](../../evidence/2026-11-06-vergabe-three-store-capture-return.json).
The matched populated point and restart checks pass; the full helper took
98.61 seconds. Both accounts work after restart, with an overview-list UI
follow-up. Off-host publication and isolated restore remain open. The command
below is retained for reproducibility; **do not recapture this accepted point**.
Next: [encrypt and fetch the frozen point](../2026-11-06-vergabe-recovery-export/README.md).
Live production changes require the founder's go for this change under
`the-custodian/docs/agent-environment-orientation.md` section 0. The following
command is prepared for that later maintenance window:

View file

@ -24,10 +24,21 @@ passes at Helm revision 4 with the expected healthy deployment/database and both
Bound claims. The [November 6 capture check](evidence/2026-11-06-vergabe-capture-preflight-return.json)
also passes: two active members and OIDC identities, fixture 1/1/1, matching file,
valid local-state header, anonymous download denial, no pending migrations and
the reader Pod server dry-run. Next is the founder-approved pause/capture/resume
in the [three-store recovery packet](proposals/2026-11-06-vergabe-three-store-capture/README.md).
the reader Pod server dry-run. The founder-approved capture then executed using
the [three-store recovery packet](proposals/2026-11-06-vergabe-three-store-capture/README.md).
Neither preflight nor synthetic validation satisfies the pilot recovery gate.
The [populated capture and resume](evidence/2026-11-06-vergabe-three-store-capture-return.json)
pass: 39 PostgreSQL tables / 247 rows, one PDF and SQLite integrity/link checks;
the helper was removed. Total operation time was 98.61 seconds, including
resume/postflight, rather than a separately measured outage duration.
The [human restart return](evidence/2026-11-06-vergabe-post-restart-user-return.json)
confirms both accounts work and everything else appears as before, except the
tender is absent from Übersicht. The deployed dashboard lists only status 1–9;
final statuses 10–13 would explain exclusion. The actual current status is not
yet reported, so this remains a UI follow-up. Off-host publication and isolated
restore remain unverified.
The other session does not update automatically, and a fresh login was needed
after a short interval. The user wants a full working day without renewed login
and would prefer no OTP at initial app sign-in, with refinement explicitly
@ -93,7 +104,8 @@ could not read native node, Deployment and PVC status. The founder's subsequent
[capture preflight](evidence/2026-11-06-vergabe-capture-preflight-return.json)
clear that blocker at Helm revision 4. They use the founder's own terminal and
existing SSH/sudo lane; the agent receives only sanitized receipts. Native
capture and restart have not run.
capture and automated restart verification subsequently passed; see the capture
receipt above. No additional pause is needed to transfer that frozen point.
After the populated workflow, prepare the exact attended recovery action from
the existing [pilot recovery contract](vergabe-teilnahme-pilot.md#persistence-and-recovery)
@ -122,8 +134,8 @@ and [deployment binding](vergabe-demo-company-binding.md). Its receipt must cove
Existing database-only backup/restore targets default to historical `vergabe_db`
and omit both file stores. They cannot establish this three-store recovery claim.
The two-account functional walkthrough is user-confirmed with UI follow-up.
The attended capture/restart action is prepared and its live preflight passes;
execution awaits the founder's go. Off-host publication, isolated native restore
and rollback remain outstanding.
The attended capture/restart action has executed successfully, with automated
and human restart checks (overview follow-up above). Off-host publication,
isolated restore and rollback remain outstanding.
Logged-in account deactivation remains a separate owner-run access-control check
from the pilot contract. No account is disabled as part of these walkthrough steps.

View file

@ -3,6 +3,14 @@
Updated 2026-11-06 under RAPPS-WP-0014 and VERGABE-WP-0019.
Release binding is complete (RAPPS-WP-0014-T02). Recovery and invited-recipient acceptance remain open.
November 6 recovery update: the founder's matched PostgreSQL/media/SQLite capture
and app resume pass at revision 4; the full operation took 98.61 seconds. Both
accounts work after restart, with an overview-list UI follow-up. See the
[capture receipt](evidence/2026-11-06-vergabe-three-store-capture-return.json).
Provider publication/readback, isolated restore, rollback/access and operating
ownership remain open. The accepted point can be transferred without another
pause using the [encrypted export packet](proposals/2026-11-06-vergabe-recovery-export/README.md).
| Item | Current binding |
| --- | --- |
| Tenant | tenant:trial:demo-company, active/version 1; three native memberships and one linked directory identity |