From 1eefbfc44a06458ae3cedaf1e79186384c5f558c Mon Sep 17 00:00:00 2001 From: tegwick Date: Sun, 11 Oct 2026 03:07:31 +0200 Subject: [PATCH] Document exact native catalogue gap and bounded owner proposal Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a126e1-76f8-7643-8cf3-e93336539ade --- .../canonical-records.json | 69 ++++++++++++++ .../keycape-client-presence.json | 8 ++ .../native-entry-metadata.json | 24 +++++ .../native-preflight.json | 12 +++ .../owner-proposal.md | 27 ++++++ .../preflight.py | 15 +++ .../proposal.json | 26 +++++ .../routing-discovery.json | 94 +++++++++++++++++++ .../run-preflight.py | 21 +++++ 9 files changed, 296 insertions(+) create mode 100644 docs/evidence/2026-10-11-one-app-catalogue-proposal/canonical-records.json create mode 100644 docs/evidence/2026-10-11-one-app-catalogue-proposal/keycape-client-presence.json create mode 100644 docs/evidence/2026-10-11-one-app-catalogue-proposal/native-entry-metadata.json create mode 100644 docs/evidence/2026-10-11-one-app-catalogue-proposal/native-preflight.json create mode 100644 docs/evidence/2026-10-11-one-app-catalogue-proposal/owner-proposal.md create mode 100644 docs/evidence/2026-10-11-one-app-catalogue-proposal/preflight.py create mode 100644 docs/evidence/2026-10-11-one-app-catalogue-proposal/proposal.json create mode 100644 docs/evidence/2026-10-11-one-app-catalogue-proposal/routing-discovery.json create mode 100644 docs/evidence/2026-10-11-one-app-catalogue-proposal/run-preflight.py diff --git a/docs/evidence/2026-10-11-one-app-catalogue-proposal/canonical-records.json b/docs/evidence/2026-10-11-one-app-catalogue-proposal/canonical-records.json new file mode 100644 index 0000000..d4be6a8 --- /dev/null +++ b/docs/evidence/2026-10-11-one-app-catalogue-proposal/canonical-records.json @@ -0,0 +1,69 @@ +{ + "application": { + "application_id": "informed-decision", + "display_name": "Informed Decision", + "owner": "informed-decision", + "allowed_profile_scopes": [ + "global" + ], + "allowed_projection_types": [ + "application_runtime" + ] + }, + "binding": { + "application_id": "informed-decision", + "oidc_client_id": "informed-decision-approver", + "protected_system_id": "informed-decision", + "catalog_namespaces": [], + "event_source": null, + "deployment_ref": null + }, + "canonical_store_rows": [ + { + "record_type": "applications", + "record_key": "informed-decision", + "payload": { + "application_id": "informed-decision", + "display_name": "Informed Decision", + "owner": "informed-decision", + "allowed_profile_scopes": [ + "global" + ], + "allowed_projection_types": [ + "application_runtime" + ] + }, + "tenant": null, + "user_id": null, + "application_id": "informed-decision", + "scope_type": null, + "scope_id": null + }, + { + "record_type": "application_bindings", + "record_key": "informed-decision", + "payload": { + "application_id": "informed-decision", + "oidc_client_id": "informed-decision-approver", + "protected_system_id": "informed-decision", + "catalog_namespaces": [], + "event_source": null, + "deployment_ref": null + }, + "tenant": null, + "user_id": null, + "application_id": "informed-decision", + "scope_type": null, + "scope_id": null + } + ], + "application_owner": "informed-decision", + "local_registry_owner": "user-engine", + "protected_system_owner": "access-engine", + "oidc_client_owner": "key-cape", + "entry_url_evidence": "https://decisions.coulomb.social/", + "entry_url_persisted": false, + "entry_url_reason": "Canonical Application/ApplicationBinding model has no entry URL field. URL is separate verified Ingress context, never an invented persisted field.", + "creates_user_permissions": false, + "scope": "One application record and one exact binding; no memberships, roles, grants or user creation." +} diff --git a/docs/evidence/2026-10-11-one-app-catalogue-proposal/keycape-client-presence.json b/docs/evidence/2026-10-11-one-app-catalogue-proposal/keycape-client-presence.json new file mode 100644 index 0000000..3ee7923 --- /dev/null +++ b/docs/evidence/2026-10-11-one-app-catalogue-proposal/keycape-client-presence.json @@ -0,0 +1,8 @@ +{ + "read_only": true, + "secret_objects_read": false, + "real_human_login_performed": false, + "method": "Known client rejects unregistered redirect with native KeyCape redirect_uri error; no login/cookie/state output.", + "http_status": 400, + "registered_client_rejects_wrong_redirect": true +} diff --git a/docs/evidence/2026-10-11-one-app-catalogue-proposal/native-entry-metadata.json b/docs/evidence/2026-10-11-one-app-catalogue-proposal/native-entry-metadata.json new file mode 100644 index 0000000..6a80712 --- /dev/null +++ b/docs/evidence/2026-10-11-one-app-catalogue-proposal/native-entry-metadata.json @@ -0,0 +1,24 @@ +{ + "ingress_read": true, + "secret_objects_read": false, + "entries": [ + { + "name": "informed-decision", + "uid": "98d3885a-a62d-49c2-91ea-6616fa5a04ae", + "hosts": [ + "decisions.coulomb.social" + ], + "tls_hosts": [ + "decisions.coulomb.social" + ] + }, + { + "name": "informed-decision-http-redirect", + "uid": "550279fb-c9a1-4585-9b21-27b1c8f90b6d", + "hosts": [ + "decisions.coulomb.social" + ], + "tls_hosts": [] + } + ] +} diff --git a/docs/evidence/2026-10-11-one-app-catalogue-proposal/native-preflight.json b/docs/evidence/2026-10-11-one-app-catalogue-proposal/native-preflight.json new file mode 100644 index 0000000..69464da --- /dev/null +++ b/docs/evidence/2026-10-11-one-app-catalogue-proposal/native-preflight.json @@ -0,0 +1,12 @@ +{ + "application_absent": true, + "binding_absent": true, + "exact_match": false, + "fixed_application_id": "informed-decision", + "native_mutation": false, + "partial_or_conflicting": false, + "read_only": true, + "pod_uid": "e500bcae-c911-43a2-bd40-6a30b39064ab", + "pod_image_match": true, + "native_exec_returncode": 0 +} diff --git a/docs/evidence/2026-10-11-one-app-catalogue-proposal/owner-proposal.md b/docs/evidence/2026-10-11-one-app-catalogue-proposal/owner-proposal.md new file mode 100644 index 0000000..b57fd19 --- /dev/null +++ b/docs/evidence/2026-10-11-one-app-catalogue-proposal/owner-proposal.md @@ -0,0 +1,27 @@ +# Exact one-application catalogue owner proposal + +The live readback adapter is admitted and working. The fixed read-only preflight on its actual published Ready pod proves application informed-decision and its binding are both absent. Exact model/serialized records are attached; no mutation occurred. Existing application metadata registration is owned by User Engine, application facts by informed-decision, OIDC client by KeyCape and protected-system/client contract by Access Engine. Application-owner acknowledgment of the exact facts is required before native registration. + +## Exact facts and limits + +Application: id informed-decision, display name Informed Decision, owner informed-decision, default global profile scope and application-runtime projection type only. Binding: application informed-decision, OIDC client informed-decision-approver, protected system informed-decision, empty catalog_namespaces, no event_source or deployment_ref. No user, membership, role, entitlement or grant is created. Access's actual registry declares this participant/client/issuer, and actual KeyCape independently rejects its wrong callback. Actual ingress UID98d3885a-a62d-49c2-91ea-6616fa5a04ae binds TLS host decisions.coulomb.social. Canonical Application/ApplicationBinding has no entry URL field, so https://decisions.coulomb.social/ is retained only as context. It is not silently stored in deployment_ref, event_source or a made-up schema field. The local row alone does not prove every fleet workload or scoped mutation/grant contract. + +## Existing supported authenticated path + +Existing source method is UserEngineService.register_application(verified_operator_actor, application, binding=binding). It checks absence, calls application.register through the normal FlexAuth adapter, atomically stores app/binding, and appends normal AuditRecord plus application.registered OutboxEvent. The genuine actor must come from the existing cryptographically verified User Engine identity boundary. Existing source accepts platform-operator or tenant-admin roles in its package, but this proposal grants neither and may not invent either label. A founder memo approval is not a JWT or authenticated actor. Synthetic actors used for readback policy tests must never authorize this mutation. + +Warden route searches found no User Engine management/registration lane. The KeyCape attended OIDC route is not an application.register adapter or grant. Reuse declaration describes library-import/headless consumption and remains draft. Portal/runtime source has no HTTP route for register_application, and no installed operator invocation bridging a real authenticated actor into this headless method was found. The expression above is a supported source API, not an available end-to-end native command. No credentials, login permission, endpoint or helper framework was requested or added. + +## Proposed alternative requiring a distinct founder decision + +If the owner cannot supply the supported genuine authenticated invocation promptly, the founder may choose a one-time supervised administrative bootstrap exception for exactly the attached two metadata entities. It must be presented truthfully as maintenance outside the ordinary application.register actor/PDP admission, never as a simulated founder JWT/session or a successful PDP-authorized user transaction. This packet does not implement that exception and is not ready for execution until a bounded exact executor, independent owner review and database rollback/dry-run receipt are prepared. + +Closed proposed scope: connect through the existing admitted User Engine service database connection without exporting its URL; require the exact current workload/source/schema and target database; serializable transaction and owner lock; compare target app/binding and related records; permit only both absent, or both exact match (no-change). Any partial/different state refuses. Insert exactly the two canonical codec rows using create-only semantics, not the store's unconditional upsert; record actual maintenance actor issuer urn:manual-maintenance and supervised Codex operation identity with the founder approval/proposal reference, no asserted human roles/assurance and no fabricated PDP decision_id. Append a truthful AuditRecord action application.metadata.bootstrap and an ordinary application.registered outbox event with explicit maintenance_exception/proposal/approval attribution in its metadata payload; no normal user creation or privilege claim. These audit/outbox details need owner validation against actual codec/event consumers before approval of execution. Commit only after bounded readback matches exactly; retain row/audit/event IDs and payload hashes as a created-only receipt. The actual operation and its created audit/outbox footprints must all appear in the final founder packet, not just 'two rows'. Direct cost estimate EUR0 on existing resources; engineering time and maintenance-auth exception are the material cost/risk. + +Rollback is conditional created-only maintenance, not a generic delete API (none exists for this registration). In an owner-reviewed transaction compare recorded created row IDs/types/payload hashes, prove no later dependent records or subsequent modification, and remove only the two application entities. Retain original audit/event history and record actual rollback attribution. If the registration event was delivered or claimed, stop for owner reconciliation/compensating-event review; do not erase evidence or assert downstream reversal. No blind replay, overwrite or removal of shared/preexisting records. An exact-match no-change outcome has no undo authority. This conditional recovery contract and event handling must be concrete before asking the founder to execute the alternative. + +If chosen, record the precise temporary relaxation in Custodian docs/security-close-down-checklist.md: ordinary application.register authenticated actor/PDP admission bypassed only for this one metadata bootstrap; User Engine owns restoration by installing a supported authenticated management path, acceptance evidence and migration before customer production. The current packet is only a proposal; no active relaxation is asserted or checklist entry falsely marked executed. Approval should expire2026-10-12T23:59:59Z, be single-use and exact-source-bound, with no future login privilege or autopilot promotion. + +## Acceptance after either approved native path + +Repeat admitted User Engine DB/application/binding and runtime catalogue checks without persisted fixtures. Require exactly the real three-way bound informed-decision workload and unchanged native allow/deny/unavailable/expiry behavior. Record whether the account-page catalogue uses that persisted row; browser/MFA proof remains independently human. USER26/28 close only their actual required contract scope, not merely a transport or seeded-row success. Attach work to those existing tasks; do not create another planner or copied task list. diff --git a/docs/evidence/2026-10-11-one-app-catalogue-proposal/preflight.py b/docs/evidence/2026-10-11-one-app-catalogue-proposal/preflight.py new file mode 100644 index 0000000..7d36001 --- /dev/null +++ b/docs/evidence/2026-10-11-one-app-catalogue-proposal/preflight.py @@ -0,0 +1,15 @@ +"""Fixed READ ONLY preflight for one proposed catalogue registration; never writes.""" +import os,json,datetime,hashlib +from pathlib import Path +from user_engine.domain import Application,ApplicationBinding,ProfileScope,ProjectionType +from user_engine.store_records import store_record_for +from user_engine.adapters.postgres import PostgresUserEngineStore +import psycopg +application=Application('informed-decision','Informed Decision','informed-decision',allowed_profile_scopes=(ProfileScope.GLOBAL,),allowed_projection_types=(ProjectionType.APPLICATION_RUNTIME,)) +binding=ApplicationBinding('informed-decision',oidc_client_id='informed-decision-approver',protected_system_id='informed-decision',catalog_namespaces=(),event_source=None,deployment_ref=None) +out={'fixed_application_id':'informed-decision','read_only':True,'native_mutation':False} +try: + with psycopg.connect(os.environ['USER_ENGINE_DATABASE_URL']) as conn: + conn.execute('SET TRANSACTION READ ONLY');store=PostgresUserEngineStore(conn);a=store.application('informed-decision');b=store.binding('informed-decision');out.update(application_absent=a is None,binding_absent=b is None,exact_match=a==application and b==binding,partial_or_conflicting=not ((a is None and b is None) or (a==application and b==binding)));conn.rollback() +except Exception as e:out['exception_class']=type(e).__name__ +print(json.dumps(out,sort_keys=True)) diff --git a/docs/evidence/2026-10-11-one-app-catalogue-proposal/proposal.json b/docs/evidence/2026-10-11-one-app-catalogue-proposal/proposal.json new file mode 100644 index 0000000..8c29fc5 --- /dev/null +++ b/docs/evidence/2026-10-11-one-app-catalogue-proposal/proposal.json @@ -0,0 +1,26 @@ +{ + "proposal_id": "USER-CATALOGUE-INFDEC-20261011-R1", + "status": "owner-proposal-no-native-write", + "beneficiary_tasks": [ + "USER-WP-0026-T03", + "USER-WP-0028-T02" + ], + "target": "User Engine catalogue in user-engine-pg on railiance01", + "preferred_existing_contract": "UserEngineService.register_application(real_verified_operator_actor, Application, binding=ApplicationBinding)", + "native_authenticated_management_entrypoint_found": false, + "ordinary_pdp_action": "application.register", + "ordinary_mutation_transaction": "app/binding + actual audit/application.registered outbox", + "proposed_alternative": "One-time supervised administrative bootstrap exception, only if founder explicitly chooses after exact owner-reviewed executor/dry-run is prepared. No bypass is implemented by this packet.", + "expiration_if_selected": "2026-10-12T23:59:59Z", + "approval_required": true, + "approval_grants_iam_claims": false, + "new_endpoint": false, + "new_login_permission": false, + "new_generic_helper_framework": false, + "rollback_prerequisites": [ + "exact created app and binding payloads still match", + "no later dependent records or changed payloads", + "outbox delivery/consumer side effects reconciled; refuse blind event deletion" + ], + "risk": "Administrative alternative skips the ordinary application.register actor/PDP admission for exactly this metadata registration, requiring explicit maintenance attribution and recorded relaxation. It is not an authenticated user-engine transaction or simulated human session." +} diff --git a/docs/evidence/2026-10-11-one-app-catalogue-proposal/routing-discovery.json b/docs/evidence/2026-10-11-one-app-catalogue-proposal/routing-discovery.json new file mode 100644 index 0000000..6c9af70 --- /dev/null +++ b/docs/evidence/2026-10-11-one-app-catalogue-proposal/routing-discovery.json @@ -0,0 +1,94 @@ +[ + { + "query": "user-engine application registration administrative management", + "command_success": true, + "matches": [ + { + "id": "openbao-structure-survey", + "owner_repo": "ops-mason", + "warden_executes": false, + "exec_capable": false, + "resolvable": false, + "status": "active" + }, + { + "id": "agent-harness-forgejo-deploy", + "owner_repo": "railiance-platform", + "warden_executes": false, + "exec_capable": true, + "resolvable": true, + "status": "active" + }, + { + "id": "coulomb-social-runtime-env", + "owner_repo": "railiance-platform", + "warden_executes": false, + "exec_capable": false, + "resolvable": false, + "status": "active" + }, + { + "id": "keycape-client-secret-generate", + "owner_repo": "railiance-platform", + "warden_executes": false, + "exec_capable": false, + "resolvable": false, + "status": "active" + }, + { + "id": "net-kingdom-privacyidea-admin-token", + "owner_repo": "railiance-platform", + "warden_executes": false, + "exec_capable": false, + "resolvable": false, + "status": "active" + } + ] + }, + { + "query": "key-cape human operator OIDC login", + "command_success": true, + "matches": [ + { + "id": "key-cape-oidc-login", + "owner_repo": "key-cape", + "warden_executes": false, + "exec_capable": true, + "resolvable": false, + "status": "active" + }, + { + "id": "keycape-client-secret-generate", + "owner_repo": "railiance-platform", + "warden_executes": false, + "exec_capable": false, + "resolvable": false, + "status": "active" + }, + { + "id": "rapp-qonto-keycape-client", + "owner_repo": "key-cape", + "warden_executes": false, + "exec_capable": true, + "resolvable": true, + "status": "active" + }, + { + "id": "agent-harness-forgejo-deploy", + "owner_repo": "railiance-platform", + "warden_executes": false, + "exec_capable": true, + "resolvable": true, + "status": "active" + }, + { + "id": "openbao-api-key", + "owner_repo": "railiance-platform", + "warden_executes": false, + "exec_capable": true, + "resolvable": false, + "status": "active" + } + ] + } +] diff --git a/docs/evidence/2026-10-11-one-app-catalogue-proposal/run-preflight.py b/docs/evidence/2026-10-11-one-app-catalogue-proposal/run-preflight.py new file mode 100644 index 0000000..aa1fdde --- /dev/null +++ b/docs/evidence/2026-10-11-one-app-catalogue-proposal/run-preflight.py @@ -0,0 +1,21 @@ +import json,subprocess,base64 +from pathlib import Path +probe=Path('/tmp/user-catalogue-preflight.py').read_bytes() +remote=r''' +import json,subprocess,base64,sys +r=subprocess.run(['kubectl','get','pods','-n','user-engine','-l','app.kubernetes.io/name=user-engine','-o','json'],capture_output=True,text=True) +if r.returncode:print(json.dumps({'pod_selection_success':False}));sys.exit(1) +pods=[p for p in json.loads(r.stdout)['items'] if p.get('status',{}).get('phase')=='Running' and any(c['type']=='Ready' and c['status']=='True' for c in p.get('status',{}).get('conditions',[]))] +if len(pods)!=1:print(json.dumps({'pod_selection_success':False,'ready_pod_count':len(pods)}));sys.exit(1) +p=pods[0] +if p['spec']['containers'][0]['image']!='forgejo.coulomb.social/coulomb/user-engine@sha256:f239bbf332b8eb87320c86390fddca1dcb4f7c628a7af75e79dee8058d446a7b':print(json.dumps({'image_match':False}));sys.exit(1) +r=subprocess.run(['kubectl','exec','-i','-n','user-engine',p['metadata']['name'],'-c','portal','--','python3','-'],input=base64.b64decode('__PROBE__'),capture_output=True) +try:out=json.loads(r.stdout) +except Exception:out={'native_probe_output_valid':False,'raw_output_suppressed':True} +out['pod_uid']=p['metadata']['uid'];out['pod_image_match']=True;out['native_exec_returncode']=r.returncode +print(json.dumps(out)) +'''.replace('__PROBE__',base64.b64encode(probe).decode()) +r=subprocess.run(['ssh','railiance01','python3 -'],input=remote,text=True,capture_output=True) +try:out=json.loads(r.stdout) +except Exception:out={'native_probe_output_valid':False,'raw_output_suppressed':True} +Path('/tmp/user-catalogue-preflight.json').write_text(json.dumps(out,indent=2)+'\n');print(json.dumps(out))