Record verified Backup account activation and consumer refresh
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a06ecb-456a-71c2-b41e-0755d336e883
This commit is contained in:
parent
b6d648bfbe
commit
cb6396caab
7 changed files with 160 additions and 6 deletions
|
|
@ -30,6 +30,7 @@
|
||||||
| task | RPF-WP-0027-T06 | wait | — | workplans/RPF-WP-0027-keycape-live-secret-exposure-recovery.md |
|
| task | RPF-WP-0027-T06 | wait | — | workplans/RPF-WP-0027-keycape-live-secret-exposure-recovery.md |
|
||||||
| task | RPF-WP-0029-T01 | done | — | workplans/RPF-WP-0029-backup-credential-default-removal.md |
|
| task | RPF-WP-0029-T01 | done | — | workplans/RPF-WP-0029-backup-credential-default-removal.md |
|
||||||
| task | RPF-WP-0029-T02 | wait | — | workplans/RPF-WP-0029-backup-credential-default-removal.md |
|
| task | RPF-WP-0029-T02 | wait | — | workplans/RPF-WP-0029-backup-credential-default-removal.md |
|
||||||
|
| task | RPF-WP-0029-T03 | done | — | workplans/RPF-WP-0029-backup-credential-default-removal.md |
|
||||||
| task | RPF-WP-0035-T01 | done | — | workplans/RPF-WP-0035-credential-lane-implementation.md |
|
| task | RPF-WP-0035-T01 | done | — | workplans/RPF-WP-0035-credential-lane-implementation.md |
|
||||||
| task | RPF-WP-0035-T02 | wait | — | workplans/RPF-WP-0035-credential-lane-implementation.md |
|
| task | RPF-WP-0035-T02 | wait | — | workplans/RPF-WP-0035-credential-lane-implementation.md |
|
||||||
| task | RPF-WP-0035-T03 | wait | — | workplans/RPF-WP-0035-credential-lane-implementation.md |
|
| task | RPF-WP-0035-T03 | wait | — | workplans/RPF-WP-0035-credential-lane-implementation.md |
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ request_type: workload-kv-read
|
||||||
title: Railiance offsite backup lane (Nextcloud WebDAV + age recovery)
|
title: Railiance offsite backup lane (Nextcloud WebDAV + age recovery)
|
||||||
status: active
|
status: active
|
||||||
created: '2026-07-07'
|
created: '2026-07-07'
|
||||||
updated: '2026-07-16'
|
updated: '2026-09-05'
|
||||||
requester:
|
requester:
|
||||||
agent: grok
|
agent: grok
|
||||||
reason: Move railiance-backup / forgejo-backup credentials from hardcoded script
|
reason: Move railiance-backup / forgejo-backup credentials from hardcoded script
|
||||||
|
|
@ -72,6 +72,12 @@ risk:
|
||||||
classification: high
|
classification: high
|
||||||
notes:
|
notes:
|
||||||
- NC_WEBDAV_TOKEN grants upload to the offsite backup file drop.
|
- NC_WEBDAV_TOKEN grants upload to the offsite backup file drop.
|
||||||
|
- Since 2026-09-05 the file drop belongs to Backup, folder /railiance-backups,
|
||||||
|
with create-only permissions and a server-enforced 10 GiB account quota.
|
||||||
|
- Operator credentials remain in KVv2 operators/nextcloud/backup, fields
|
||||||
|
BACKUP_USERNAME and BACKUP_PASSWORD; never deliver them to production.
|
||||||
|
- Existing Bernd-owned retained backups and recovery access remain separate;
|
||||||
|
historical predecessor invalidation and age-key exposure are still open.
|
||||||
- "AGE_PRIVATE_KEY decrypts all age-encrypted backup artifacts \u2014 recovery escrow\
|
- "AGE_PRIVATE_KEY decrypts all age-encrypted backup artifacts \u2014 recovery escrow\
|
||||||
\ only."
|
\ only."
|
||||||
- Credentials must not be stored on production hosts with delete permission.
|
- Credentials must not be stored on production hosts with delete permission.
|
||||||
|
|
@ -117,6 +123,17 @@ verification:
|
||||||
- 'Field presence via JSON key inventory only (NC_WEBDAV_TOKEN, NC_WEBDAV_URL, AGE_PRIVATE_KEY); lengths recorded, values not printed.'
|
- 'Field presence via JSON key inventory only (NC_WEBDAV_TOKEN, NC_WEBDAV_URL, AGE_PRIVATE_KEY); lengths recorded, values not printed.'
|
||||||
- 'EXPOSED taint set: custom_metadata exposed_at=2026-07-16T00:00:00Z exposed_version=2 (WP-0026 T05).'
|
- 'EXPOSED taint set: custom_metadata exposed_at=2026-07-16T00:00:00Z exposed_version=2 (WP-0026 T05).'
|
||||||
- 'ops-warden catalog promoted draft→active; fetch_command pinned to NC_WEBDAV_TOKEN; resolvable=true; risk=high.'
|
- 'ops-warden catalog promoted draft→active; fetch_command pinned to NC_WEBDAV_TOKEN; resolvable=true; risk=high.'
|
||||||
|
- at: '2026-09-05'
|
||||||
|
actor: codex
|
||||||
|
kind: dedicated_backup_account_cutover
|
||||||
|
result: passed
|
||||||
|
details:
|
||||||
|
- User authorized dedicated Backup account and operator custody coordinates.
|
||||||
|
- Verified 10737418240-byte quota and Backup-owned create-only share.
|
||||||
|
- Encrypted fixture PUT 201, owner download and escrow decryption passed;
|
||||||
|
runtime GET and DELETE returned 405 on the actual upload endpoint.
|
||||||
|
- CAS advanced workload KV version 2 to 3, preserving age escrow and other fields.
|
||||||
|
- Evidence docs/evidence/RPF-WP-0029-backup-account-2026-09-05.json.
|
||||||
|
|
||||||
lifecycle:
|
lifecycle:
|
||||||
deactivate: Disable ops-warden catalog entry and detach OIDC role policy; rotate
|
deactivate: Disable ops-warden catalog entry and detach OIDC role policy; rotate
|
||||||
|
|
|
||||||
|
|
@ -65,3 +65,36 @@ requires HTTPS and rejects non-success responses. The Python backend streams
|
||||||
the artifact, refuses redirects and suppresses credential-bearing exception
|
the artifact, refuses redirects and suppresses credential-bearing exception
|
||||||
text. These source changes are preparation; no provider rotation, upload or
|
text. These source changes are preparation; no provider rotation, upload or
|
||||||
restore is claimed by their tests.
|
restore is claimed by their tests.
|
||||||
|
|
||||||
|
## Dedicated Backup account (2026-09-05)
|
||||||
|
|
||||||
|
The operator-provisioned account is `Backup` on `nx4069.your-storageshare.de`.
|
||||||
|
Its credentials remain in OpenBao KVv2 `operators/nextcloud/backup`, fields
|
||||||
|
`BACKUP_USERNAME` and `BACKUP_PASSWORD` (API `operators/data/nextcloud/backup`).
|
||||||
|
The UI's `secrets/` prefix is not a separate KV mount.
|
||||||
|
|
||||||
|
Future uploads use the account's `/railiance-backups` folder through a dedicated
|
||||||
|
create-only share. Only its derived `NC_WEBDAV_TOKEN` and `NC_WEBDAV_URL` enter
|
||||||
|
the existing workload lane and activity-core ExternalSecret; the account password
|
||||||
|
is not a production credential. Recovery download and cleanup use operator
|
||||||
|
account authority. Preserve `AGE_PRIVATE_KEY` and all unrelated KV fields with CAS.
|
||||||
|
|
||||||
|
The server-reported quota is **10 GiB (10,737,418,240 bytes)**. This is a hard
|
||||||
|
capacity limit shared by the account's files. Retention counts such as 14 daily
|
||||||
|
and four weekly backups do not guarantee they fit. Check quota before large
|
||||||
|
uploads; a quota rejection is a failed backup. Pruning retained backups requires
|
||||||
|
an explicit retention decision and operator authority; upload jobs cannot delete.
|
||||||
|
Existing Bernd-owned backups remain in their original location and require their
|
||||||
|
existing recovery access. This cutover neither migrates them nor revokes Bernd's
|
||||||
|
personal account or old share.
|
||||||
|
|
||||||
|
`scripts/migrate_nextcloud_backup_account.py` performs the attended account,
|
||||||
|
quota, create-only share, encrypted fixture recovery and CAS checks. Run it only
|
||||||
|
through `warden access openbao-platform-admin-login --exec -- ...`, with a fresh
|
||||||
|
private receipt path and `--confirm 'MIGRATE TO Backup'`. The helper is silent;
|
||||||
|
receipts contain only status and metadata. Review a failed receipt before retrying:
|
||||||
|
a failure can leave the dedicated folder/share or an identified test fixture, and
|
||||||
|
a cleanup failure after CAS can occur after credentials have already changed.
|
||||||
|
Refresh `actcore-backup-offsite`, verify delivery by contained comparison, and
|
||||||
|
restart its three environment consumers (`actcore-api`, `actcore-event-router`,
|
||||||
|
`actcore-worker`). Record their readiness and loaded-value comparisons.
|
||||||
|
|
|
||||||
60
docs/evidence/RPF-WP-0029-backup-account-2026-09-05.json
Normal file
60
docs/evidence/RPF-WP-0029-backup-account-2026-09-05.json
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
{
|
||||||
|
"date": "2026-09-05",
|
||||||
|
"cutover": {
|
||||||
|
"schema": "platform.nextcloud-backup-account-cutover.v1",
|
||||||
|
"status": "account_cutover_verified_pending_consumer_refresh",
|
||||||
|
"quota_before": {
|
||||||
|
"quota_bytes": 10737418240,
|
||||||
|
"used_bytes": 2506112,
|
||||||
|
"available_bytes": 10734912128
|
||||||
|
},
|
||||||
|
"previous_kv_version": 2,
|
||||||
|
"share_id": "19",
|
||||||
|
"observed_permissions": 4,
|
||||||
|
"owner_matches": true,
|
||||||
|
"path_matches": true,
|
||||||
|
"share_owner": "Backup",
|
||||||
|
"share_permissions": 4,
|
||||||
|
"fixture_name": "account-acceptance-ee8a5e360afd26b7dc7b9b4c.age",
|
||||||
|
"upload_http_status": 201,
|
||||||
|
"runtime_get_http_status": 405,
|
||||||
|
"runtime_delete_http_status": 405,
|
||||||
|
"encrypted_upload": true,
|
||||||
|
"owner_download": true,
|
||||||
|
"escrow_decryption": true,
|
||||||
|
"runtime_read_denied": true,
|
||||||
|
"runtime_delete_denied": true,
|
||||||
|
"kv_version": 3,
|
||||||
|
"escrow_preserved": true,
|
||||||
|
"fixture_removed": true,
|
||||||
|
"quota_after": {
|
||||||
|
"quota_bytes": 10737418240,
|
||||||
|
"used_bytes": 2506112,
|
||||||
|
"available_bytes": 10734912128
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"consumers": {
|
||||||
|
"status": "verified",
|
||||||
|
"kv_version": 3,
|
||||||
|
"eso_delivery_matches": true,
|
||||||
|
"deployments": {
|
||||||
|
"actcore-api": {
|
||||||
|
"ready": true,
|
||||||
|
"environment_matches": true
|
||||||
|
},
|
||||||
|
"actcore-event-router": {
|
||||||
|
"ready": true,
|
||||||
|
"environment_matches": true
|
||||||
|
},
|
||||||
|
"actcore-worker": {
|
||||||
|
"ready": true,
|
||||||
|
"environment_matches": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"previous_test_fixtures_removed": [
|
||||||
|
"account-acceptance-e820d52ac48dc28766c39eef.age",
|
||||||
|
"account-acceptance-f88f8dcc3bea4ea199aeeebd.age"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"status": "verified"
|
||||||
|
}
|
||||||
|
|
@ -40,6 +40,12 @@ Decrypt: `~/.config/age/railiance-backup.key` (same key as other Railiance backu
|
||||||
|
|
||||||
## Nextcloud layout
|
## Nextcloud layout
|
||||||
|
|
||||||
|
Since 2026-09-05, uploads go to user `Backup`, folder `/railiance-backups`,
|
||||||
|
through a create-only share delivered from OpenBao. The account has **10 GiB**
|
||||||
|
total capacity; the retention target below is subject to available space.
|
||||||
|
Operator credentials stay in `operators/nextcloud/backup`; workload jobs receive
|
||||||
|
only the derived upload grant. See [account and recovery procedure](backup-credential-recovery.md).
|
||||||
|
|
||||||
```
|
```
|
||||||
forgejo/forgejo-dump-<timestamp>.zip.age
|
forgejo/forgejo-dump-<timestamp>.zip.age
|
||||||
forgejo/forgejo-db-<timestamp>.sql.age
|
forgejo/forgejo-db-<timestamp>.sql.age
|
||||||
|
|
|
||||||
29
history/2026-09-05-nextcloud-backup-account-cutover.md
Normal file
29
history/2026-09-05-nextcloud-backup-account-cutover.md
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Dedicated Nextcloud Backup account activated — 2026-09-05
|
||||||
|
|
||||||
|
User authorized replacing Bernd's personal upload lane with the new Backup
|
||||||
|
account. Resolved UI custody notation to KVv2 operators/nextcloud/backup
|
||||||
|
(BACKUP_USERNAME/BACKUP_PASSWORD). Native WebDAV confirmed Backup and a
|
||||||
|
10,737,418,240-byte account quota.
|
||||||
|
|
||||||
|
Created /railiance-backups and backup prefix folders, with a Backup-owned public
|
||||||
|
share granting create only (permissions 4). Account password remains operator-only.
|
||||||
|
An initial publicUpload option broadened the share; verification rejected it and
|
||||||
|
removed that share before touching workload custody. Explicit permissions alone
|
||||||
|
produced the required grant. The actual file-drop endpoint denies GET and DELETE
|
||||||
|
with HTTP 405. Three encrypted synthetic fixtures exercised transport/recovery;
|
||||||
|
all were removed using owner authority after verification.
|
||||||
|
|
||||||
|
Uploaded with HTTP 201, downloaded as owner, and decrypted with existing age
|
||||||
|
escrow. CAS advanced the workload lane from version 2 to 3, changing only the
|
||||||
|
upload token and URL. Forced actcore-backup-offsite refresh and compared values
|
||||||
|
in protected memory. Restarted actcore-api, actcore-event-router and actcore-worker;
|
||||||
|
all ready with new values loaded. No password or token appears in source/evidence.
|
||||||
|
|
||||||
|
10 GiB is a hard account limit, not assurance that 14 daily plus four weekly
|
||||||
|
backups fit. No retained backup deletion or automatic pruning was performed.
|
||||||
|
Existing Bernd-owned backups and recovery access remain where they were.
|
||||||
|
T03 is done; T02 remains waiting for old share invalidation and a real offsite
|
||||||
|
application restore. Upload rotation does not clear historical age-key exposure.
|
||||||
|
|
||||||
|
Validation: 196 repository tests passed. Live evidence is in
|
||||||
|
`docs/evidence/RPF-WP-0029-backup-account-2026-09-05.json`.
|
||||||
|
|
@ -4,7 +4,7 @@ type: workplan
|
||||||
title: "Remove backup credential default and verify governed replacement"
|
title: "Remove backup credential default and verify governed replacement"
|
||||||
domain: financials
|
domain: financials
|
||||||
repo: railiance-platform
|
repo: railiance-platform
|
||||||
status: active
|
status: blocked
|
||||||
owner: codex
|
owner: codex
|
||||||
created: "2026-09-05"
|
created: "2026-09-05"
|
||||||
updated: "2026-09-05"
|
updated: "2026-09-05"
|
||||||
|
|
@ -44,11 +44,12 @@ state_hub_task_id: "b3f3402f-890b-5781-9b3e-1c9c0d28cea8"
|
||||||
Provider-side invalidation and replacement custody need the attended provider owner and CCR-2026-0004 lifecycle procedure. Record only non-secret invalidation, encrypted upload and restore receipts. No provider authority or replacement receipt was available; source removal alone does not close the reported exposure. Never record the predecessor value, fingerprint, length, or shape.
|
Provider-side invalidation and replacement custody need the attended provider owner and CCR-2026-0004 lifecycle procedure. Record only non-secret invalidation, encrypted upload and restore receipts. No provider authority or replacement receipt was available; source removal alone does not close the reported exposure. Never record the predecessor value, fingerprint, length, or shape.
|
||||||
|
|
||||||
Prepared owner execution procedure: `docs/backup-credential-recovery.md`.
|
Prepared owner execution procedure: `docs/backup-credential-recovery.md`.
|
||||||
Awaiting the Nextcloud share owner/account and replacement custody coordinates;
|
The dedicated Backup account cutover is complete under T03. Awaiting owner
|
||||||
OpenBao authority is not provider share-management authority. Activity-core is
|
authority for invalidating the old Bernd-owned share and a real offsite restore. Activity-core is
|
||||||
also a consumer of this upload lane. Preserve AGE_PRIVATE_KEY and historical
|
also a consumer of this upload lane. Preserve AGE_PRIVATE_KEY and historical
|
||||||
exposure evidence; upload-token rotation cannot clear recovery-key taint.
|
exposure evidence; upload-token rotation cannot clear recovery-key taint.
|
||||||
No provider mutation, backup upload or restore has been run in this continuation.
|
T03 proves encrypted fixture transport and decryption; full application restore
|
||||||
|
and historical predecessor invalidation remain open.
|
||||||
|
|
||||||
## Portfolio review — 2026-09-05
|
## Portfolio review — 2026-09-05
|
||||||
|
|
||||||
|
|
@ -64,7 +65,7 @@ here until its evidence is accepted. No rotation was executed in this review.
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: RPF-WP-0029-T03
|
id: RPF-WP-0029-T03
|
||||||
status: progress
|
status: done
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "f85b1b4e-9a20-56e2-9e7d-d1d6f1c77bd9"
|
state_hub_task_id: "f85b1b4e-9a20-56e2-9e7d-d1d6f1c77bd9"
|
||||||
```
|
```
|
||||||
|
|
@ -78,3 +79,10 @@ for workload delivery, and preserve the existing age escrow and retained data.
|
||||||
Prove encrypted upload/download/decryption and workload delivery. No automatic
|
Prove encrypted upload/download/decryption and workload delivery. No automatic
|
||||||
pruning or personal-account revocation is inferred from this account change.
|
pruning or personal-account revocation is inferred from this account change.
|
||||||
The historical predecessor invalidation obligation in T02 remains separate.
|
The historical predecessor invalidation obligation in T02 remains separate.
|
||||||
|
|
||||||
|
Completed 2026-09-05: Backup-owned share permissions 4; upload HTTP 201,
|
||||||
|
owner download/decryption passed, runtime GET/DELETE denied with HTTP 405.
|
||||||
|
Workload KV CAS 2→3 preserved age escrow. ExternalSecret delivery and all three
|
||||||
|
activity-core deployments verified ready with new credentials loaded. All test
|
||||||
|
fixtures removed. Account quota is enforced by Nextcloud; no automatic pruning.
|
||||||
|
Evidence: `docs/evidence/RPF-WP-0029-backup-account-2026-09-05.json`.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue