Document exact native catalogue gap and bounded owner proposal
Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a126e1-76f8-7643-8cf3-e93336539ade
This commit is contained in:
parent
f0f67a55ce
commit
1eefbfc44a
9 changed files with 296 additions and 0 deletions
|
|
@ -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."
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
|
@ -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))
|
||||
|
|
@ -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."
|
||||
}
|
||||
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
@ -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))
|
||||
Loading…
Add table
Add a link
Reference in a new issue