Record functional pilot walkthrough and prepare attended inventory handoff
Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a1abf1-7e95-7141-87c9-ee78332bf790
This commit is contained in:
parent
177a85d05f
commit
fab81f0086
5 changed files with 221 additions and 6 deletions
29
docs/evidence/2026-11-05-vergabe-functional-flow-return.json
Normal file
29
docs/evidence/2026-11-05-vergabe-functional-flow-return.json
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"schema": "railiance.vergabe-pilot-user-return.v1",
|
||||
"reported_on": "2026-11-05",
|
||||
"workplan": "RAPPS-WP-0014",
|
||||
"task": "RAPPS-WP-0014-T03",
|
||||
"evidence_source": "User confirmation in the active conversation",
|
||||
"evidence_kind": "user_reported",
|
||||
"fixture": {"ausschreibung_id": 1, "aufgabe_id": 1, "dokument_id": 1},
|
||||
"cross_account_task_editing_works": true,
|
||||
"user_reports_flow_completed": true,
|
||||
"final_recorded_phase_user_label": "Zuschlag/Nachlese",
|
||||
"user_assessment": "The flow needs work, but the functionality present seems to work quite well.",
|
||||
"functional_walkthrough_status": "confirmed_with_ui_followup",
|
||||
"ui_review_status": "open",
|
||||
"individual_approval_records_independently_verified": false,
|
||||
"native_inventory_complete": false,
|
||||
"populated_restart_or_recovery_verified": false,
|
||||
"session_or_otp_policy_changed": false,
|
||||
"runtime_mutations_by_agent": false,
|
||||
"remaining_work": [
|
||||
"Attended native release/storage inventory",
|
||||
"File checksum and direct anonymous-download refusal",
|
||||
"Owner-run inactive-session denial",
|
||||
"Populated pod-replacement verification",
|
||||
"Coherent PostgreSQL/media/issue-state off-host recovery point",
|
||||
"Isolated restored workflow and compatible rollback",
|
||||
"Backup and incident/support ownership, cadence, retention and recovery objectives"
|
||||
]
|
||||
}
|
||||
|
|
@ -36,6 +36,36 @@ new standing agent grant is requested by the packet. The result must report
|
|||
`native_inventory_complete: true` before using its expected release as the
|
||||
baseline of a separately reviewed capture/restart operation.
|
||||
|
||||
## Founder-terminal handoff
|
||||
|
||||
The user has now confirmed cross-account task edits and the functional flow
|
||||
through Zuschlag/Nachlese, with UI follow-up. The remaining first step is native
|
||||
inventory. A restricted SSH check as `custodian-agt` was refused at authentication;
|
||||
the agent did not try an elevated account or issue its own certificate.
|
||||
|
||||
From a synced `railiance-apps` checkout on **railiance01**, run:
|
||||
|
||||
```bash
|
||||
python3 tools/vergabe_pilot_inventory_attended.py --submit
|
||||
```
|
||||
|
||||
The launcher asks for the **path** to the existing gexec approver key. The normal
|
||||
gexec review/signature step follows. It stages the fixed proposal in the existing
|
||||
exchange directory, then uses `sudo -u custodian-agt` only to enqueue the signed
|
||||
request under the required UID and read its sanitized result. Kubernetes access
|
||||
runs through gexec's configured `kube:railiance01` target. The founder needs the
|
||||
existing exchange access and ability to use that restricted account via sudo.
|
||||
No new key, standing grant or privileged kubeconfig is installed. Keep the
|
||||
approver key in its existing custody. If it is held only on the workstation,
|
||||
sign the action there with the existing gexec CLI and supply that public signed
|
||||
approval on the node with `--submit --approval /path/to/approval.json`; do not
|
||||
copy the private key to the node. Gexec verifies the signature and its expiry.
|
||||
|
||||
Share the final result JSON. A pending result retains its request ID; inspect
|
||||
that request before submitting again. The launcher defaults to local packet
|
||||
review when `--submit` is omitted and refuses a changed action digest. The
|
||||
existing gated executor remains responsible for signature/nonce/profile checks.
|
||||
|
||||
Validation: source compilation and synthetic command responses cover success,
|
||||
immediate wrong-cluster refusal, image drift and exclusion of a private canary
|
||||
from the receipt. Ruff is unavailable in the current shell. No native pass,
|
||||
|
|
|
|||
|
|
@ -10,8 +10,12 @@ the [document return](evidence/2026-11-05-vergabe-document-return.json). The
|
|||
document UI still needs user review. File hash equality and signed-out download
|
||||
refusal are unverified. The user also confirms the **LOKAL** issue badge is
|
||||
visible in both accounts; the [issue return](evidence/2026-11-05-vergabe-local-issue-return.json)
|
||||
binds Ausschreibung 1, task 1 and document 1 from their supplied URLs. Task
|
||||
edits, domain approval/submission and recovery remain pending.
|
||||
binds Ausschreibung 1, task 1 and document 1 from their supplied URLs. The user
|
||||
now confirms cross-account task editing and the flow through documented
|
||||
**Zuschlag/Nachlese**, with further UI work needed; see the
|
||||
[functional-flow return](evidence/2026-11-05-vergabe-functional-flow-return.json).
|
||||
The functional walkthrough is confirmed with UI follow-up. The instructions
|
||||
below remain the reproduction sequence for the populated restart/restore drill.
|
||||
|
||||
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
|
||||
|
|
@ -107,8 +111,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.
|
||||
Two-account sign-in and cross-account visibility of newly created records are
|
||||
user-confirmed; the remaining shared workflow is pending. The attended restart,
|
||||
The two-account functional walkthrough is user-confirmed with UI follow-up.
|
||||
The attended restart,
|
||||
off-host capture, isolated restore and rollback action has not been prepared or executed.
|
||||
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.
|
||||
|
|
|
|||
135
tools/vergabe_pilot_inventory_attended.py
Normal file
135
tools/vergabe_pilot_inventory_attended.py
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Founder-terminal review, signing and submission of the fixed pilot inventory.
|
||||
|
||||
Run on railiance01 from a synced railiance-apps checkout. Default only reviews
|
||||
the packet. --submit uses the existing approver key and gated executor; the
|
||||
request is staged as custodian-agt so the executor's submitter check is retained.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import stat
|
||||
import subprocess
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
|
||||
EXPECTED = "sha256:2014e62a84b0875fec155dbfd1be26963d9a39ab931092d26c5dfb9e627ffbd7"
|
||||
PACKET = (Path(__file__).resolve().parents[1]
|
||||
/ "docs/proposals/2026-11-05-vergabe-recovery-preflight/action.json")
|
||||
GEXEC = Path("/usr/local/bin/gexec")
|
||||
EXCHANGE = Path("/var/spool/gexec/exchange")
|
||||
SPOOL = "/var/spool/gexec"
|
||||
|
||||
READ_RESULT = """
|
||||
import json, pathlib, re, sys, time
|
||||
request_id = sys.argv[1]
|
||||
if not re.fullmatch(r'vergabe-inventory-[0-9a-f]{16}', request_id):
|
||||
raise SystemExit(1)
|
||||
directory = pathlib.Path('/var/spool/gexec/results')
|
||||
for attempt in range(60):
|
||||
matches = list(directory.glob(request_id + '.*.json'))
|
||||
if len(matches) == 1:
|
||||
result = json.loads(matches[0].read_text())
|
||||
print(json.dumps(result, indent=2))
|
||||
raise SystemExit(0 if result.get('status') == 'executed'
|
||||
and result.get('exit_code') == 0 else 1)
|
||||
if len(matches) > 1:
|
||||
print(json.dumps({'status': 'ambiguous_result', 'request_id': request_id}))
|
||||
raise SystemExit(1)
|
||||
time.sleep(1)
|
||||
print(json.dumps({'status': 'result_pending', 'request_id': request_id,
|
||||
'instruction': 'Preserve this request id; inspect its result before resubmitting.'}))
|
||||
raise SystemExit(2)
|
||||
"""
|
||||
|
||||
|
||||
def validated_packet(path=PACKET):
|
||||
packet = json.loads(path.read_text())
|
||||
encoded = json.dumps(packet["action"], sort_keys=True, separators=(",", ":"),
|
||||
ensure_ascii=False, allow_nan=False).encode()
|
||||
digest = "sha256:" + hashlib.sha256(encoded).hexdigest()
|
||||
if digest != EXPECTED or packet.get("digest") != EXPECTED:
|
||||
raise ValueError("packet_digest_mismatch")
|
||||
return packet
|
||||
|
||||
|
||||
def submit(packet, key=None, approval_file=None):
|
||||
info = GEXEC.resolve(strict=True).stat()
|
||||
if info.st_uid != 0 or not stat.S_ISREG(info.st_mode) or info.st_mode & 0o022:
|
||||
raise ValueError("admitted_root_owned_gexec_required")
|
||||
if EXCHANGE.is_symlink() or not EXCHANGE.is_dir():
|
||||
raise ValueError("admitted_exchange_required")
|
||||
request_id = "vergabe-inventory-" + uuid.uuid4().hex[:16]
|
||||
proposal = EXCHANGE / (request_id + ".action.json")
|
||||
approval = EXCHANGE / (request_id + ".approval.json")
|
||||
fd = os.open(proposal, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o644)
|
||||
with os.fdopen(fd, "w") as output:
|
||||
json.dump(packet, output, indent=2)
|
||||
if approval_file is not None:
|
||||
signed = json.loads(approval_file.read_text())
|
||||
if signed.get("payload", {}).get("digest") != EXPECTED:
|
||||
raise ValueError("approval_digest_mismatch")
|
||||
fd = os.open(approval, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o644)
|
||||
with os.fdopen(fd, "w") as output:
|
||||
json.dump(signed, output)
|
||||
else:
|
||||
# The existing CLI displays the exact action and asks the founder to sign.
|
||||
approved = subprocess.run([
|
||||
str(GEXEC), "approve", str(proposal), "--key", str(key),
|
||||
"--approver", "bernd", "--ttl", "900", "--out", str(approval),
|
||||
], check=False)
|
||||
if approved.returncode:
|
||||
print(json.dumps({"status": "not_submitted", "request_id": request_id}))
|
||||
return 1
|
||||
queued = subprocess.run([
|
||||
"/usr/bin/sudo", "-u", "custodian-agt", str(GEXEC), "submit",
|
||||
"--spool", SPOOL, "--proposal", str(proposal), "--approval", str(approval),
|
||||
"--request-id", request_id,
|
||||
], check=False)
|
||||
if queued.returncode:
|
||||
print(json.dumps({"status": "submission_unconfirmed", "request_id": request_id,
|
||||
"instruction": "Inspect this request before creating another."}))
|
||||
return 1
|
||||
return subprocess.run([
|
||||
"/usr/bin/sudo", "-u", "custodian-agt", "/usr/bin/python3", "-c",
|
||||
READ_RESULT, request_id,
|
||||
], check=False).returncode
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--submit", action="store_true")
|
||||
signing = parser.add_mutually_exclusive_group()
|
||||
signing.add_argument("--key", type=Path, help="Path to the existing gexec approver key")
|
||||
signing.add_argument("--approval", type=Path, help="Existing signed approval; keeps key in its custody")
|
||||
args = parser.parse_args(argv)
|
||||
packet = validated_packet()
|
||||
print(json.dumps({"status": "prepared", "digest": EXPECTED,
|
||||
"scope": "Read-only Vergabe deployment/storage inventory",
|
||||
"target": "kube:railiance01", "runtime_mutations": False}), flush=True)
|
||||
if not args.submit:
|
||||
return 0
|
||||
if not GEXEC.is_file():
|
||||
raise ValueError("admitted_gexec_missing")
|
||||
if args.key is None and args.approval is None:
|
||||
args.key = Path(input("Path to your existing gexec approver key: ").strip()).expanduser()
|
||||
return submit(packet, args.key, args.approval)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
raise SystemExit(main())
|
||||
except ValueError as error:
|
||||
failure = str(error)
|
||||
if failure not in {"packet_digest_mismatch", "approval_digest_mismatch", "admitted_gexec_missing",
|
||||
"admitted_root_owned_gexec_required", "admitted_exchange_required"}:
|
||||
failure = "invalid_packet_or_runtime"
|
||||
print(json.dumps({"status": "launcher_failed", "failure": failure}))
|
||||
raise SystemExit(1)
|
||||
except Exception:
|
||||
print(json.dumps({"status": "launcher_failed", "failure": "attended_runtime_unavailable"}))
|
||||
raise SystemExit(1)
|
||||
|
|
@ -196,10 +196,10 @@ id: RAPPS-WP-0014-T03
|
|||
status: wait
|
||||
needs_human: true
|
||||
decision_id: d06307e5-2737-461a-a2f4-a12c3b492a9a
|
||||
intervention_note: "Both accounts sign in and see created records, the uploaded document and LOKAL issue (2026-11-05). Fixture: Ausschreibung/task/document 1. Remaining shared task edit, approval/submission and access checks precede populated restart/recovery. Exact metadata-only inventory packet is prepared; current caller lacks native reads. Off-host recovery, isolated restore, rollback and ownership remain open. Document UI review stays pending; session/OTP refinement is deferred."
|
||||
intervention_note: "Two-account functional walkthrough through Zuschlag/Nachlese is user-confirmed with UI follow-up (2026-11-05); task edits, document and LOKAL issue work. Fixture: Ausschreibung/task/document 1. Next: run the prepared attended native inventory; current caller lacks native reads and restricted agent SSH authentication was refused. Populated restart/off-host recovery, isolated restore, rollback, access evidence and operating ownership remain open."
|
||||
priority: high
|
||||
assignee: the-custodian
|
||||
blocking_reason: "Await populated two-user/document workflow, coherent PostgreSQL/media/issue-state off-host recovery point, isolated restored workflow, rollback evidence and support ownership. September 25 proves database restore and restart only."
|
||||
blocking_reason: "Two-account functional walkthrough is confirmed with UI follow-up. Await attended native inventory, populated restart, coherent PostgreSQL/media/issue-state off-host recovery, isolated restored workflow, rollback/access evidence and operating ownership. September 25 proves database-only restore and restart."
|
||||
state_hub_task_id: "dd069c6d-fcc1-5bac-b233-976f2f0d5cd1"
|
||||
```
|
||||
|
||||
|
|
@ -321,6 +321,23 @@ the platform primary-archive helper currently has no Vergabe application profile
|
|||
Off-host publication/readback still needs its owner-bound storage/custody path.
|
||||
T03 remains wait for the remaining workflow and operational recovery evidence.
|
||||
|
||||
2026-11-05 functional-flow return: the user confirms task editing works and
|
||||
reports completing the flow through documented Zuschlag/Nachlese. Existing
|
||||
functionality works quite well in their review, while UI work remains. Receipt:
|
||||
`docs/evidence/2026-11-05-vergabe-functional-flow-return.json`. The two-account
|
||||
functional walkthrough is now confirmed with UI follow-up; no repeat baseline
|
||||
walkthrough is requested. Native recovery, byte/access checks and operating
|
||||
ownership remain open, and the broader decision/task are not closed.
|
||||
|
||||
The routed restricted SSH check as custodian-agt was refused at authentication;
|
||||
no elevated account was attempted. Route `agt-custodian-ssh-cert` identifies
|
||||
supervisor-only issuance. Prepared
|
||||
`tools/vergabe_pilot_inventory_attended.py` for the founder terminal on
|
||||
railiance01: it validates the exact existing proposal, obtains the normal gexec
|
||||
signature, submits as custodian-agt to preserve the request UID check, and
|
||||
returns the sanitized result. Default mode only reviews the packet. This
|
||||
prepares an attended read-only inventory, not permission for a snapshot/restart.
|
||||
|
||||
|
||||
## Validate synthetic sizing against the exact release and shared contention
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue