Bind Vergabe pilot fixtures and prepare native recovery preflight
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s

Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a1abf1-7e95-7141-87c9-ee78332bf790
This commit is contained in:
tegwick 2026-11-05 22:29:23 +01:00
parent cb7582de55
commit 177a85d05f
8 changed files with 327 additions and 2 deletions

View file

@ -0,0 +1,35 @@
{
"schema": "railiance.vergabe-pilot-anonymous-page-probes.v1",
"observed_at": "2026-11-05T21:27:44.219543+00:00",
"runtime_mutations": false,
"reads": [
{
"path": "/demo-company/ausschreibungen/1/",
"method": "GET",
"cookies_supplied": false,
"final_status": 200,
"final_host": "vergabe-teilnahme.coulomb.social",
"final_path": "/demo-company/accounts/login/",
"netkingdom_welcome_present": true
},
{
"path": "/demo-company/ausschreibungen/1/aufgaben/1/",
"method": "GET",
"cookies_supplied": false,
"final_status": 200,
"final_host": "vergabe-teilnahme.coulomb.social",
"final_path": "/demo-company/accounts/login/",
"netkingdom_welcome_present": true
},
{
"path": "/demo-company/ausschreibungen/1/dokumente/1/",
"method": "GET",
"cookies_supplied": false,
"final_status": 200,
"final_host": "vergabe-teilnahme.coulomb.social",
"final_path": "/demo-company/accounts/login/",
"netkingdom_welcome_present": true
}
],
"binary_document_download_tested": false
}

View file

@ -0,0 +1,23 @@
{
"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 and application URLs in the active conversation",
"evidence_kind": "user_reported",
"company": "demo-company",
"local_issue_badge_visible_in_both_accounts": true,
"exact_issue_key_independently_verified": false,
"fixture": {
"ausschreibung_id": 1,
"aufgabe_id": 1,
"dokument_id": 1,
"task_url": "https://vergabe-teilnahme.coulomb.social/demo-company/ausschreibungen/1/aufgaben/1/",
"document_detail_url": "https://vergabe-teilnahme.coulomb.social/demo-company/ausschreibungen/1/dokumente/1/"
},
"document_ui_review": "pending",
"populated_restart_or_recovery_verified": false,
"personal_account_identifiers_recorded": false,
"credentials_or_tokens_recorded": false,
"runtime_mutations_by_agent": false
}

View file

@ -0,0 +1,20 @@
{
"schema": "railiance.vergabe-pilot-native-inventory.v1",
"observed_at": "2026-11-05T21:25:35.760984+00:00",
"runtime_mutations": false,
"native_inventory_complete": false,
"cluster_read": "ok",
"cluster_matches_expected": true,
"nodes_read": "forbidden",
"deployment_read": "forbidden",
"claims": {
"media": {
"read": "forbidden"
},
"app-state": {
"read": "forbidden"
}
},
"database_cluster_read": "forbidden",
"helm_read": "request_failed"
}

View file

@ -0,0 +1,42 @@
# Vergabe native recovery inventory
Prepared under RAPPS-WP-0014-T03. The user has identified Ausschreibung 1,
task 1 and document 1, and confirmed the local issue is visible to both accounts.
This packet prepares the native metadata read needed before a populated restart
and coherent three-store recovery action can be pinned.
The [action](action.json) embeds the complete source of
[`tools/vergabe_pilot_inventory.py`](../../../tools/vergabe_pilot_inventory.py)
as one `python3 -c` argument, bound to `kube:railiance01`, profile `kube-admin`,
agent `custodian-agt`, cwd `/` and an empty proposed environment.
Action digest:
`sha256:2014e62a84b0875fec155dbfd1be26963d9a39ab931092d26c5dfb9e627ffbd7`.
Source SHA256:
`b610059b5d7398138062de51edab3555b973cfbb61f02fa684184852805d7507`.
The command reads the cluster UID, node conditions, the exact pilot Deployment,
the two named PVCs, `databases/apps-pg` status and Helm release summaries. It
checks the recorded immutable image, Recreate/single-writer readiness and exact
mounts. Child output/errors are captured; the receipt contains booleans,
read-status codes and Helm revision. It stops immediately on a different cluster.
There are no resource mutations, pod exec, application queries or file captures.
The current caller's [inventory receipt](../../evidence/2026-11-05-vergabe-native-inventory.json)
is incomplete: the cluster UID matches, while node, Deployment, PVC and CNPG
reads are forbidden and Helm listing fails. This caller did not execute a
privileged proposal. The workstation has no installed `gexec` command; proposal
preparation used the existing gated-executor source CLI/action format only.
For attended execution, review this exact JSON with `gexec show` in the admitted
founder runtime, sign it with that runtime's existing approver key and submit
through its configured spool. The environment orientation §6 requires the
gated executor for privileged actions. No signing key, elevated kubeconfig or
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.
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,
snapshot, restart, off-host publication or restore has occurred.

File diff suppressed because one or more lines are too long

View file

@ -8,7 +8,10 @@ the other account after reload; see the [workflow return](evidence/2026-11-05-ve
The user confirmed the uploaded file is available from the other account; see
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. Task edits, local-issue workflow and recovery remain pending.
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.
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
@ -74,6 +77,9 @@ confirms the recorded cluster UID, public health and the NetKingdom welcome
gate. Node, Deployment and PVC reads are forbidden to the current agent identity;
fresh image/release/claim status remains unverified. The binding's expected image
and claims are historical reference values until a permitted native readback.
The [native inventory packet](proposals/2026-11-05-vergabe-recovery-preflight/README.md)
now provides the exact metadata-only action; its current-caller receipt remains
incomplete. It prepares the baseline read, rather than a snapshot or restart.
After the populated workflow, prepare the exact attended recovery action from
the existing [pilot recovery contract](vergabe-teilnahme-pilot.md#persistence-and-recovery)

View file

@ -0,0 +1,162 @@
#!/usr/bin/env python3
"""Read-only, value-free recovery inventory for the demo-company pilot.
Uses the caller's existing kubectl/Helm context for resource status and Helm
release summaries. No Secret output, values, logs, pod exec or resource changes.
Child output/errors stay private.
"""
from __future__ import annotations
import datetime
import json
import subprocess
CLUSTER_UID = "a553c742-0115-43d4-99a4-a5ca56fe0786"
NAMESPACE = "vergabe-demo-company"
RELEASE = "vergabe-teilnahme"
IMAGE = (
"forgejo.coulomb.social/coulomb/vergabe-teilnahme@sha256:"
"a26444f59c259698159c69ccb96f73dc648a261ece4c86bb2037a9d977870d91"
)
CLAIMS = {"media": "vergabe-teilnahme-media", "app-state": "vergabe-teilnahme-app-state"}
def read_json(argv):
try:
result = subprocess.run(argv, capture_output=True, timeout=20, check=False)
if result.returncode:
return None, "forbidden" if b"Forbidden" in result.stderr else "request_failed"
return json.loads(result.stdout), "ok"
except (OSError, subprocess.TimeoutExpired, ValueError, UnicodeError):
return None, "unavailable_or_invalid_response"
def kube(*args):
return read_json(["kubectl", "--request-timeout=12s", *args, "-o", "json"])
def collect():
receipt = {
"schema": "railiance.vergabe-pilot-native-inventory.v1",
"observed_at": datetime.datetime.now(datetime.timezone.utc).isoformat(),
"runtime_mutations": False,
"native_inventory_complete": False,
}
cluster, status = kube("get", "namespace", "kube-system")
receipt["cluster_read"] = status
if cluster is None:
return receipt
receipt["cluster_matches_expected"] = cluster.get("metadata", {}).get("uid") == CLUSTER_UID
if not receipt["cluster_matches_expected"]:
return receipt
nodes, status = kube("get", "nodes")
receipt["nodes_read"] = status
if nodes is not None:
matching = [
n for n in nodes.get("items", [])
if any(a.get("address") == "92.205.62.239"
for a in n.get("status", {}).get("addresses", []))
]
receipt["node_address_matches_expected"] = len(matching) == 1
if len(matching) == 1:
conditions = {c.get("type"): c.get("status")
for c in matching[0].get("status", {}).get("conditions", [])}
receipt["node_ready"] = conditions.get("Ready") == "True"
receipt["node_pressure_clear"] = all(
conditions.get(c) == "False"
for c in ("MemoryPressure", "DiskPressure", "PIDPressure")
)
deployment, status = kube("get", "deployment", RELEASE, "-n", NAMESPACE)
receipt["deployment_read"] = status
if deployment is not None:
spec = deployment.get("spec", {})
pod = spec.get("template", {}).get("spec", {})
app = next((c for c in pod.get("containers", []) if c.get("name") == "app"), {})
ready = deployment.get("status", {})
receipt["deployment"] = {
"image_matches_expected": app.get("image") == IMAGE,
"replicas": spec.get("replicas"),
"ready_replicas": ready.get("readyReplicas", 0),
"updated_replicas": ready.get("updatedReplicas", 0),
"generation_observed": ready.get("observedGeneration", 0)
>= deployment.get("metadata", {}).get("generation", 1),
"recreate": spec.get("strategy", {}).get("type") == "Recreate",
"mounts_match_expected": all(
any(v.get("name") == name
and v.get("persistentVolumeClaim", {}).get("claimName") == claim
for v in pod.get("volumes", []))
for name, claim in CLAIMS.items()
) and all(
any(m.get("name") == name and m.get("mountPath") == path
for m in app.get("volumeMounts", []))
for name, path in (("media", "/app/media"), ("app-state", "/app/.issue-facade"))
),
}
receipt["claims"] = {}
for name, claim in CLAIMS.items():
data, status = kube("get", "pvc", claim, "-n", NAMESPACE)
row = {"read": status}
if data is not None:
row["bound"] = data.get("status", {}).get("phase") == "Bound"
row["identity_present"] = bool(data.get("metadata", {}).get("uid"))
receipt["claims"][name] = row
database, status = kube("get", "cluster", "apps-pg", "-n", "databases")
receipt["database_cluster_read"] = status
if database is not None:
db_status = database.get("status", {})
receipt["database_ready"] = (
db_status.get("instances", 0) > 0
and db_status.get("readyInstances", 0) == db_status.get("instances")
and bool(db_status.get("currentPrimary"))
)
releases, status = read_json([
"helm", "list", "--all", "--namespace", NAMESPACE,
"--filter", "^vergabe-teilnahme$", "--output", "json",
])
receipt["helm_read"] = status
if isinstance(releases, list):
rows = [r for r in releases if r.get("name") == RELEASE]
if len(rows) == 1:
receipt["helm"] = {
"deployed": rows[0].get("status") == "deployed",
"revision": int(rows[0]["revision"]),
"chart_matches_expected": rows[0].get("chart") == "vergabe-teilnahme-0.2.1",
}
dep = receipt.get("deployment", {})
release = receipt.get("helm", {})
receipt["native_inventory_complete"] = (
receipt.get("node_address_matches_expected") is True
and receipt.get("node_ready") is True
and receipt.get("node_pressure_clear") is True
and dep.get("image_matches_expected") is True
and dep.get("replicas") == dep.get("ready_replicas") == dep.get("updated_replicas") == 1
and dep.get("generation_observed") is True
and dep.get("recreate") is True and dep.get("mounts_match_expected") is True
and all(c.get("bound") is True and c.get("identity_present") is True
for c in receipt["claims"].values())
and receipt.get("database_ready") is True
and release.get("deployed") is True and release.get("chart_matches_expected") is True
)
return receipt
def main():
try:
receipt = collect()
except Exception:
receipt = {"schema": "railiance.vergabe-pilot-native-inventory.v1",
"native_inventory_complete": False, "failure": "invalid_inventory_response",
"runtime_mutations": False}
print(json.dumps(receipt, indent=2))
return 0 if receipt["native_inventory_complete"] else 1
if __name__ == "__main__":
raise SystemExit(main())

View file

@ -196,7 +196,7 @@ id: RAPPS-WP-0014-T03
status: wait
needs_human: true
decision_id: d06307e5-2737-461a-a2f4-a12c3b492a9a
intervention_note: "Both accounts sign in; created records and uploaded document are visible from the other account (user-confirmed 2026-11-05). Next: remaining task/local-issue and negative-access checks, then populated restart, coherent off-host recovery, isolated restore, rollback and ownership. Document UI review stays pending; session/OTP refinement is deferred. railiance-platform owns storage/custody delivery."
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."
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."
@ -300,6 +300,27 @@ acceptance, byte/hash equality, anonymous refusal and populated recovery are
not inferred. Requested the task's local issue badge/key check from both
sessions next. T03 retains its remaining workflow, recovery and ownership scope.
2026-11-05 local-issue return: the user confirms the LOKAL badge is visible
from both accounts and supplies task/document URLs, binding Ausschreibung 1,
task 1 and document 1. Receipt:
`docs/evidence/2026-11-05-vergabe-local-issue-return.json`. Signed-out HTTP reads
of these identified tender/task/document pages reach the NetKingdom login page;
the document-detail URL is not the binary file URL, so direct file refusal
remains unverified. Requested the remaining shared task-edit and domain
approval/demo-submission results together.
Prepared `tools/vergabe_pilot_inventory.py` and exact metadata-only action
`docs/proposals/2026-11-05-vergabe-recovery-preflight/action.json` for the
existing attended executor. Cluster UID matches, but the current caller's
native inventory remains incomplete (node/Deployment/PVC/CNPG reads forbidden,
Helm listing failed). No privileged proposal was executed; `gexec` is absent
from this workstation. Source compilation/synthetic success, wrong-cluster,
image-drift and output-canary checks pass. This is a preflight packet, not the
capture/restart operation. Existing database-only helpers omit both file stores;
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.
## Validate synthetic sizing against the exact release and shared contention