Add reviewed one-shot task execution journal primitive
Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a126e1-76f8-7643-8cf3-e93336539ade
This commit is contained in:
parent
d264e68436
commit
4ed50501f6
6 changed files with 619 additions and 0 deletions
|
|
@ -0,0 +1,65 @@
|
|||
{
|
||||
"completed_same_owner_refinement_precedes_formal_review": true,
|
||||
"decision": "approved",
|
||||
"input_unchanged": true,
|
||||
"intent_basis": "Platform INTENT stable shared interfaces, secure custody and observable recovery: exact provider route prerequisites and fail-closed guarded native preparation without publichealth becoming authority.",
|
||||
"mandatory_native_prerequisites": [
|
||||
"Publichealth clusterhash is unauthenticated: independently verify founder/node/Service/cluster/provider route identity, current admitted route/estate and exact source/runtime pins; no arbitrary workstation diagnostic proves node placement.",
|
||||
"Actual installed OpenBao JWT plugin/version, role/config/effective-policy source equality and raw/effective expiration_leeway, clock_skew_leeway and not_before_leeway interaction. Helm2.5.4/tag and raw0=>150 model are not native facts; semantic expiry proof remains mandatory.",
|
||||
"Establish issuer actual readiness_state and Argo ownership through authoritative source/owner receipt. No keycape declaration/current deployment adoption established in inspected sources; absence is not nonproduction. Unmapped production-tier rules apply. If adopted/production-approved, transient directCAS needs explicit reviewed one-use maintenanceexception, close-down entry and reconciliation before nativego.",
|
||||
"Fresh authenticated scoped founder decision covers exact route, source, issuer mutation/window and finite abort/revoke/restoration/recovery obligations. Helper labels/sourceacknowledgments cannot authenticate approval or waive gates.",
|
||||
"Admitted private founder human/coding-agent token producer/client/callback/custody handoff remains unimplemented. No credential request/read/reuse authorized.",
|
||||
"Native correct role/claim permutation/expiry/refusal/revoke, baseline restoration/client removal/temporaryobject absence and all unknown outcome resolution. MASON and Secrets native/full-adoption obligations stay separate."
|
||||
],
|
||||
"not_approved": [
|
||||
"route setup, native preflight/login/Secret access or production mutation",
|
||||
"privileged authority/helperapproval authentication or default flip",
|
||||
"current provider identity/plugin/leeway/readiness/Argo facts",
|
||||
"private producer or whole KEY39/RPF35T02/SecretsT06 native acceptance"
|
||||
],
|
||||
"optional_consumer_consistency_observation": {
|
||||
"manifest_sha256": "32a419752e4a3ed7cf8f906fc40ebbaa516b9a4d6134be2df29243ce97213e40",
|
||||
"notes": [
|
||||
"Explicit execute-ccr descriptor is shape/binding only; unimplemented compiler/adapter remains gate.",
|
||||
"Consumer hashes use sha256: prefix; Journal Binding uses bare64hex. The future owner mediator must define and validate exact representation conversion; do not silently join mismatched identity/digests.",
|
||||
"Execution request propagation does not satisfy caller/PDP/consume/plan/admission/body scope by itself."
|
||||
],
|
||||
"scope": "Read design/schema for Platform interoperability only; no Secrets owner review"
|
||||
},
|
||||
"ordering_caveat": "Documentation says execute checks health before protected token input, but main reads private stdin before execute invokes health. That claim is excluded from this approval. Before producer handoff/native admission, correct packet wording or implement a pre-input gate and review its exact source. Actual fail-before-native/Secret effects is verified.",
|
||||
"platform_source_pins": {
|
||||
"helm/openbao-ui-overlay-k8s.yaml": "7b345359906bf1ecc4cb8e61de7a9f1a121068a66bd919e606190a9217a82daf",
|
||||
"helm/openbao-ui-overlay/nginx.conf": "464f7f5cecc69ea343c1e2acc5932e832b2a9c0e6a5099113634a12abc80ccb3",
|
||||
"helm/openbao-values.yaml": "a10239851277889dd69dacb8636109dddd095551d85b46ca4ed2c141944e8d1e"
|
||||
},
|
||||
"review_scope": "public-health fail-before-native gate and bounded node-route proposal source only; no native route/go or pre-private-input claim",
|
||||
"reviewed_entries": {
|
||||
"sso-mfa/k8s/keycape/openbao-negative-node-route.md": "b1184d349ad8166804253edeb7932b82d1bd30eb5fe46fcc5bbda8f88593eb9d",
|
||||
"sso-mfa/k8s/keycape/openbao-negative-session.py": "11df42c873ee7ab4cf4a42fa2326ada4661703632b07745220e75a61f7c7fadf",
|
||||
"sso-mfa/k8s/keycape/test_openbao_negative_session.py": "01e23f2b4fc77824a161a57acb3a52d19aad846b3b6c0fd3abd81afa1dc2985c",
|
||||
"sso-mfa/k8s/keycape/test_openbao_node_route.py": "00e370b0c3892e16939b7e34ee070df7fe6183b8037741a33b7a6f2814847a9d"
|
||||
},
|
||||
"reviewed_manifest": "/tmp/keycape-jwt-node-route-stage/manifest.json",
|
||||
"reviewed_manifest_sha256": "23a972abc5175e121e594726d2b7f7a28c62109253f58f12623eaf2e5564a035",
|
||||
"reviewer": "railiance-platform-owner (agent railiance-platform, codex)",
|
||||
"same_trial": true,
|
||||
"schema": "owner-source-review/v1",
|
||||
"validation": {
|
||||
"commands": [
|
||||
"PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s /tmp/keycape-jwt-node-route-stage/net-kingdom/sso-mfa/k8s/keycape -p test_openbao*.py -q",
|
||||
"PYTHONDONTWRITEBYTECODE=1 /home/worsch/secrets-engine/.venv/bin/python -m pytest -q -p no:cacheprovider /tmp/platform-key39-node-route-review-stage/tests/test_platform_route.py"
|
||||
],
|
||||
"independent_checks": 6,
|
||||
"result": "passed synthetic/offline tests; native false",
|
||||
"supplied_lifecycle_and_route": 54,
|
||||
"total_fresh_checks": 60
|
||||
},
|
||||
"verified": [
|
||||
"SourceService openbao/openbao-ui-gateway8080 routes to nginx /v1 proxy for OpenBao8200; proposed dedicated node-loopback Service port-forward avoids node PodDNS assumption and shared workstation tunnel alteration. No portforward/bridge/native route executed.",
|
||||
"PublicGET only fixed /v1/sys/health, no credential header; strict initialized/unsealed/active booleans and bounded cluster-id hash, no raw public id retained.",
|
||||
"Current-process-only route-preflight performs no Kubernetes/Secret/private-stdin access, retains native_accepted=false.",
|
||||
"Execute/recovery pin health before native reads; second health check after dry-runs before first create. Missing/drift/unavailable/redirect/slow response prevents protected effects.",
|
||||
"Existing no-proxy/no-redirect/byte/mainthread-total-timer/finite-exception-abort bounds apply; failed cleanup/unknown login is not cleared by healthy route."
|
||||
],
|
||||
"work_item": "RPF-WP-0035-T13"
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"completed_owner_record_precedes_formal_review": true,
|
||||
"decision": "changes_requested",
|
||||
"finding": {
|
||||
"counterexamples": [
|
||||
"after_call(binding,False,correct_digest,evidence) confirms ordinal0",
|
||||
"after_call(binding,0.0,correct_digest,evidence) confirms ordinal0",
|
||||
"after_call(binding,'0',correct_digest,evidence) confirms ordinal0"
|
||||
],
|
||||
"finding": "after_call lacks strict ordinal and call_digest validation; SQLite coerces ill-typed ordinal into exact stored integer, allowing pending outcome to be confirmed.",
|
||||
"id": "RPF-JOURNAL-V2-F01",
|
||||
"required_change": "Apply before_call equivalent exact integer0..63 and typed lowercase64hex call_digest validation before transaction; malformed confirmation must leave pending state unchanged. Retain no-live-admission and exact one-time confirmation checks."
|
||||
},
|
||||
"inputs_unchanged": true,
|
||||
"intent_basis": "Platform INTENT Stable Interfaces/Secure Custody/Operable recovery: exact durable admission and truthful unknown external outcomes, without source prototype becoming authority.",
|
||||
"reviewed_files": {
|
||||
"scripts/task_execution_journal.py": "86b912e98eaedfa172de0f805ceb572b8c787565d4d9bbfc09b5836289a4dc3a",
|
||||
"tests/test_task_execution_journal.py": "01075296e57592ff30702cb9252c8b10133b26afe7921a084d5314107f9346c2"
|
||||
},
|
||||
"reviewed_manifest": "/tmp/platform-execution-journal-stage-v2/manifest.json",
|
||||
"reviewed_manifest_sha256": "341cac1de945d2fbe8f516119909bd44fc37e85dccfb38b451981d4de2d402e7",
|
||||
"reviewer": "railiance-platform-owner (agent railiance-platform, codex)",
|
||||
"schema": "owner-source-review/v1",
|
||||
"scope_limits": [
|
||||
"Primitive does not authenticate caller, PDP/claim/consume or exact body plan; trusted owner mediation remains required.",
|
||||
"Call ordinal/hash comes from future independent owner plan compiler; no generic backend/cleanup adapter or owner-private unknown recovery supplied.",
|
||||
"Source syntax/state tests are not native grant, source application, whole execution-contract acceptance or RPF35-T12/SecretsT06 completion."
|
||||
],
|
||||
"validation": {
|
||||
"commands": [
|
||||
"PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s /tmp/platform-execution-journal-stage-v2/tests -q",
|
||||
"PYTHONDONTWRITEBYTECODE=1 /home/worsch/secrets-engine/.venv/bin/python -m pytest -q -p no:cacheprovider /tmp/platform-journal-owner-review-stage/tests/test_independent_journal.py"
|
||||
],
|
||||
"credential_access": false,
|
||||
"independent_checks": 5,
|
||||
"native": false,
|
||||
"owner_checkout_writes": false,
|
||||
"result": "19passed including3 deliberately reproduced malformed-confirmation defects, realfork crash and privatefile check",
|
||||
"supplied_tests": 14
|
||||
},
|
||||
"verified_properties": [
|
||||
"Four actual processes contend and exactly one reserves the approval.",
|
||||
"Private existing directory, database/lock modes, symlink/hardlink rejection, FULL SQLite durability and directory fsync.",
|
||||
"Approval/operation uniqueness and full immutable binding; completed/unknown/reserved replay never reestablishes live admission.",
|
||||
"Persisted pending call blocks next call and every success transition, including consume-confirmed, until exact confirmation; process crash after intent remains unknown/nonresumable."
|
||||
],
|
||||
"work_item": "RPF-WP-0035-T11"
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"completed_record_precedes_review": true,
|
||||
"correction": "RPF-JOURNAL-V2-F01 corrected: exact integer0..63 and typed64hex call digest validated before after_call update, no SQLite bool/float/text ordinal coercion; malformed confirmations retain pending outcome then one correct confirmation passes.",
|
||||
"decision": "approved",
|
||||
"implementation_gates": [
|
||||
"Authenticate actual caller/representation and PDP/claim/consume; source methods do not authorize transitions.",
|
||||
"Independent owner plan compiler pins exact ordinal/method/target/body hashes; call hashes alone prove no method/body scope.",
|
||||
"Restricted native adapter, TTL/uses/deadline and owner-held grant/cleanup enforcement.",
|
||||
"Owner-private cleanup/recovery after unknown remains unwired: business dispatch must not resume; cleanup needs a separately admitted bounded owner recovery interface.",
|
||||
"Runtime private directory/credential isolation and actual native crash/refusal/revoke/readback proofs; source modes alone do not establish enforcement."
|
||||
],
|
||||
"intent_basis": "Platform INTENT stable interfaces, secure custody and recovery: durable one-operation admission and truthful pending outcomes without a prototype becoming authority.",
|
||||
"not_approved": [
|
||||
"native grants, production execution or source application",
|
||||
"complete mediator/whole execution contract acceptance",
|
||||
"RPF35-T12 or SecretsT06 closure or default migration"
|
||||
],
|
||||
"prior_changes_requested_retained": true,
|
||||
"prior_review": "docs/reviews/2026-10-11-task-execution-journal-v2-platform-review.json",
|
||||
"prior_review_sha256": "3ed7894f0d5f7a648c61e1c15d7404786187cc40393f95f5fc4d866613da9459",
|
||||
"review_scope": "unintegrated durable admission journal primitive source only",
|
||||
"reviewed_files": {
|
||||
"scripts/task_execution_journal.py": "866ac65af18ddabc5876cc940605d136bebfd8829fc467129d23ce2416b7716c",
|
||||
"tests/test_task_execution_journal.py": "580ad0224038b9e800ac055c6650ba8b2346be1a93a32ce1a42b54ab4776bb91"
|
||||
},
|
||||
"reviewed_input_unchanged": true,
|
||||
"reviewed_manifest": "/tmp/platform-execution-journal-stage-v3/manifest.json",
|
||||
"reviewed_manifest_sha256": "905ff6666d05df6a19d165a535579d917d7de31a43e066c2afc34a57e8cbdc9d",
|
||||
"reviewer": "railiance-platform-owner (agent railiance-platform, codex)",
|
||||
"same_trial": true,
|
||||
"schema": "owner-source-review/v1",
|
||||
"validated_properties": [
|
||||
"Actual4process race admits one operation only.",
|
||||
"Real child-process abrupt exit after fsynced reservation/pending intent survives reopen as unknown/nonresumable.",
|
||||
"Exclusive invocation, approval/operation uniqueness, immutable binding, exact call intent/confirmation and no terminal replay.",
|
||||
"Private owner directory/SQLite/lock modes and no symlink/hardlink files; FULL SQLite commits and directory sync."
|
||||
],
|
||||
"validation": {
|
||||
"commands": [
|
||||
"PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s /tmp/platform-execution-journal-stage-v3/tests -q",
|
||||
"PYTHONDONTWRITEBYTECODE=1 /home/worsch/secrets-engine/.venv/bin/python -m pytest -q -p no:cacheprovider /tmp/platform-journal-owner-review-stage/revision-v3/tests/test_independent_journal_v3.py"
|
||||
],
|
||||
"independent_regressions": 5,
|
||||
"result": "passed synthetic/local journal checks; no credentials/native action",
|
||||
"supplied_tests": 15,
|
||||
"total": 20
|
||||
},
|
||||
"work_item": "RPF-WP-0035-T11"
|
||||
}
|
||||
234
scripts/task_execution_journal.py
Normal file
234
scripts/task_execution_journal.py
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
"""Source-only admission primitive; never authorizes or dispatches native work.
|
||||
|
||||
Trusted owner mediation must validate claim/PDP/consume before transitions.
|
||||
One approval admits one operation. A persisted reservation cannot be resumed.
|
||||
The process lock is held across the whole owner invocation, including cleanup.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import fcntl
|
||||
import os
|
||||
import re
|
||||
import sqlite3
|
||||
import stat
|
||||
import uuid
|
||||
from contextlib import contextmanager
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class Refused(Exception):
|
||||
pass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Binding:
|
||||
approval_id: str
|
||||
request_digest: str
|
||||
operation_id: str
|
||||
plan_digest: str
|
||||
|
||||
def validate(self):
|
||||
if any(type(v) is not str for v in (self.approval_id, self.request_digest, self.operation_id, self.plan_digest)):
|
||||
raise Refused("binding fields must be strings")
|
||||
if not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9_-]{0,127}", self.approval_id):
|
||||
raise Refused("invalid approval identifier")
|
||||
for digest in (self.request_digest, self.plan_digest):
|
||||
if not re.fullmatch(r"[0-9a-f]{64}", digest):
|
||||
raise Refused("invalid digest")
|
||||
try:
|
||||
if str(uuid.UUID(self.operation_id)) != self.operation_id:
|
||||
raise ValueError()
|
||||
except (ValueError, AttributeError):
|
||||
raise Refused("invalid operation identifier") from None
|
||||
|
||||
|
||||
_NEXT = {
|
||||
"reserved": {"consume-confirmed", "failed", "unknown"},
|
||||
"consume-confirmed": {"authenticating", "failed", "unknown"},
|
||||
"authenticating": {"grant-issuing", "failed", "unknown"},
|
||||
"grant-issuing": {"grant-issued", "failed", "unknown"},
|
||||
"grant-issued": {"applying", "failed", "unknown"},
|
||||
"applying": {"readback", "failed", "unknown"},
|
||||
"readback": {"verified", "failed", "unknown"},
|
||||
"verified": {"cleanup-confirmed", "unknown"},
|
||||
}
|
||||
|
||||
|
||||
class Journal:
|
||||
def __init__(self, directory: Path):
|
||||
# Require an existing owner-private directory: deployment creates it.
|
||||
if directory.is_symlink() or directory.resolve() != directory.absolute():
|
||||
raise Refused("journal path is indirect")
|
||||
self.directory = directory
|
||||
self._private(directory.stat(), directory=True)
|
||||
self._lock_fd = self._open("execution.lock")
|
||||
try:
|
||||
fd = self._open("journal.sqlite")
|
||||
except BaseException:
|
||||
os.close(self._lock_fd)
|
||||
del self._lock_fd
|
||||
raise
|
||||
original = os.fstat(fd)
|
||||
os.close(fd)
|
||||
self.db = sqlite3.connect(directory / "journal.sqlite", isolation_level=None)
|
||||
current = (directory / "journal.sqlite").stat()
|
||||
if (original.st_dev, original.st_ino) != (current.st_dev, current.st_ino):
|
||||
self.close()
|
||||
raise Refused("journal changed during open")
|
||||
self.db.execute("PRAGMA synchronous=FULL")
|
||||
self.db.execute("PRAGMA journal_mode=DELETE")
|
||||
self.db.execute("CREATE TABLE IF NOT EXISTS operations (approval TEXT PRIMARY KEY, request TEXT NOT NULL, operation TEXT UNIQUE NOT NULL, plan TEXT NOT NULL, state TEXT NOT NULL, evidence TEXT)")
|
||||
self.db.execute("CREATE TABLE IF NOT EXISTS calls (operation TEXT NOT NULL, ordinal INTEGER NOT NULL, call_digest TEXT NOT NULL, outcome TEXT NOT NULL, evidence TEXT, PRIMARY KEY(operation,ordinal))")
|
||||
self._held = False
|
||||
self._admission = None
|
||||
self._sync_directory()
|
||||
|
||||
@staticmethod
|
||||
def _private(s, directory=False):
|
||||
kind = stat.S_ISDIR(s.st_mode) if directory else stat.S_ISREG(s.st_mode)
|
||||
if not kind or s.st_uid != os.getuid() or s.st_mode & 0o077:
|
||||
raise Refused("journal is not owner private")
|
||||
if not directory and s.st_nlink != 1:
|
||||
raise Refused("journal file has multiple links")
|
||||
|
||||
def _open(self, name):
|
||||
fd = os.open(self.directory / name, os.O_CREAT | os.O_RDWR | os.O_NOFOLLOW, 0o600)
|
||||
try:
|
||||
self._private(os.fstat(fd))
|
||||
except BaseException:
|
||||
os.close(fd)
|
||||
raise
|
||||
return fd
|
||||
|
||||
def _sync_directory(self):
|
||||
fd = os.open(self.directory, os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW)
|
||||
try:
|
||||
os.fsync(fd)
|
||||
finally:
|
||||
os.close(fd)
|
||||
|
||||
@contextmanager
|
||||
def locked(self):
|
||||
if self._held:
|
||||
raise Refused("nested journal admission")
|
||||
try:
|
||||
fcntl.flock(self._lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
except BlockingIOError:
|
||||
raise Refused("owner invocation already active") from None
|
||||
self._held = True
|
||||
try:
|
||||
yield self
|
||||
finally:
|
||||
self._admission = None
|
||||
self._held = False
|
||||
fcntl.flock(self._lock_fd, fcntl.LOCK_UN)
|
||||
|
||||
def reserve(self, binding: Binding):
|
||||
binding.validate()
|
||||
if not self._held or self._admission is not None:
|
||||
raise Refused("reservation requires fresh exclusive invocation")
|
||||
try:
|
||||
self.db.execute("BEGIN IMMEDIATE")
|
||||
self.db.execute("INSERT INTO operations VALUES (?,?,?,?,?,NULL)",
|
||||
(binding.approval_id, binding.request_digest,
|
||||
binding.operation_id, binding.plan_digest, "reserved"))
|
||||
self.db.execute("COMMIT")
|
||||
self._sync_directory()
|
||||
except sqlite3.IntegrityError:
|
||||
self.db.execute("ROLLBACK")
|
||||
raise Refused("approval or operation already admitted") from None
|
||||
except BaseException:
|
||||
if self.db.in_transaction:
|
||||
self.db.execute("ROLLBACK")
|
||||
raise
|
||||
self._admission = binding
|
||||
|
||||
def transition(self, binding: Binding, expected: str, target: str, evidence_digest=None):
|
||||
if not self._held or self._admission != binding:
|
||||
raise Refused("no live admission")
|
||||
if target not in _NEXT.get(expected, set()):
|
||||
raise Refused("invalid state transition")
|
||||
if target == "cleanup-confirmed" and evidence_digest is None:
|
||||
raise Refused("cleanup requires evidence")
|
||||
if evidence_digest is not None and not re.fullmatch(r"[0-9a-f]{64}", evidence_digest):
|
||||
raise Refused("invalid evidence digest")
|
||||
try:
|
||||
self.db.execute("BEGIN IMMEDIATE")
|
||||
pending=self.db.execute("SELECT COUNT(*) FROM calls WHERE operation=? AND outcome='pending'",(binding.operation_id,)).fetchone()[0]
|
||||
if pending and target != 'unknown':
|
||||
raise Refused("unconfirmed external call requires unknown")
|
||||
changed = self.db.execute(
|
||||
"UPDATE operations SET state=?, evidence=? WHERE approval=? AND request=? AND operation=? AND plan=? AND state=?",
|
||||
(target, evidence_digest, binding.approval_id, binding.request_digest,
|
||||
binding.operation_id, binding.plan_digest, expected)).rowcount
|
||||
if changed != 1:
|
||||
raise Refused("journal state changed")
|
||||
self.db.execute("COMMIT")
|
||||
self._sync_directory()
|
||||
except BaseException:
|
||||
if self.db.in_transaction:
|
||||
self.db.execute("ROLLBACK")
|
||||
raise
|
||||
|
||||
def observe(self, binding: Binding):
|
||||
binding.validate()
|
||||
row = self.db.execute("SELECT request,operation,plan,state,evidence FROM operations WHERE approval=?", (binding.approval_id,)).fetchone()
|
||||
if row is None:
|
||||
return None
|
||||
if row[:3] != (binding.request_digest, binding.operation_id, binding.plan_digest):
|
||||
raise Refused("journal binding mismatch")
|
||||
# Readback cannot create a live admission, even for an interrupted state.
|
||||
pending = self.db.execute("SELECT COUNT(*) FROM calls WHERE operation=? AND outcome='pending'", (binding.operation_id,)).fetchone()[0]
|
||||
return {"state": row[3], "evidence_digest": row[4], "dispatch_allowed": False,
|
||||
"external_outcome_unknown": bool(pending)}
|
||||
|
||||
def before_call(self, binding: Binding, ordinal: int, call_digest: str):
|
||||
"""Persist one exact plan-call intent before the mediator issues it.
|
||||
|
||||
Caller must derive ordinal/digest from the independently pinned owner plan.
|
||||
This primitive doesn't validate method/body or decide whether a call is allowed.
|
||||
"""
|
||||
if not self._held or self._admission != binding:
|
||||
raise Refused("no live admission")
|
||||
if type(ordinal) is not int or ordinal < 0 or ordinal > 63:
|
||||
raise Refused("invalid fixed-plan ordinal")
|
||||
if type(call_digest) is not str or not re.fullmatch(r"[0-9a-f]{64}", call_digest):
|
||||
raise Refused("invalid call digest")
|
||||
try:
|
||||
self.db.execute("BEGIN IMMEDIATE")
|
||||
count,pending = self.db.execute("SELECT COUNT(*), COALESCE(SUM(outcome='pending'),0) FROM calls WHERE operation=?",(binding.operation_id,)).fetchone()
|
||||
state=self.db.execute("SELECT state FROM operations WHERE operation=?",(binding.operation_id,)).fetchone()[0]
|
||||
if ordinal != count or pending or state in {'failed','unknown','cleanup-confirmed'}:
|
||||
raise Refused("call is replayed, uncertain or terminal")
|
||||
self.db.execute("INSERT INTO calls VALUES (?,?,?,'pending',NULL)",(binding.operation_id,ordinal,call_digest))
|
||||
self.db.execute("COMMIT")
|
||||
self._sync_directory()
|
||||
except BaseException:
|
||||
if self.db.in_transaction: self.db.execute("ROLLBACK")
|
||||
raise
|
||||
|
||||
def after_call(self, binding: Binding, ordinal: int, call_digest: str, evidence_digest: str):
|
||||
if not self._held or self._admission != binding:
|
||||
raise Refused("no live admission")
|
||||
if type(ordinal) is not int or ordinal < 0 or ordinal > 63:
|
||||
raise Refused("invalid fixed-plan ordinal")
|
||||
if type(call_digest) is not str or not re.fullmatch(r"[0-9a-f]{64}", call_digest):
|
||||
raise Refused("invalid call digest")
|
||||
if type(evidence_digest) is not str or not re.fullmatch(r"[0-9a-f]{64}", evidence_digest):
|
||||
raise Refused("invalid evidence digest")
|
||||
try:
|
||||
self.db.execute("BEGIN IMMEDIATE")
|
||||
n=self.db.execute("UPDATE calls SET outcome='complete', evidence=? WHERE operation=? AND ordinal=? AND call_digest=? AND outcome='pending'",(evidence_digest,binding.operation_id,ordinal,call_digest)).rowcount
|
||||
if n != 1: raise Refused("call confirmation mismatch")
|
||||
self.db.execute("COMMIT")
|
||||
self._sync_directory()
|
||||
except BaseException:
|
||||
if self.db.in_transaction: self.db.execute("ROLLBACK")
|
||||
raise
|
||||
|
||||
def close(self):
|
||||
if hasattr(self, "db"):
|
||||
self.db.close()
|
||||
if hasattr(self, "_lock_fd"):
|
||||
os.close(self._lock_fd)
|
||||
168
tests/test_task_execution_journal.py
Normal file
168
tests/test_task_execution_journal.py
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
import importlib.util
|
||||
import multiprocessing
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
|
||||
spec = importlib.util.spec_from_file_location('task_execution_journal', Path(__file__).resolve().parents[1] / 'scripts/task_execution_journal.py')
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[spec.name] = module
|
||||
spec.loader.exec_module(module)
|
||||
Binding, Journal, Refused = module.Binding, module.Journal, module.Refused
|
||||
|
||||
|
||||
def reserve_worker(directory, binding, gate, results):
|
||||
journal = Journal(Path(directory))
|
||||
gate.wait()
|
||||
try:
|
||||
with journal.locked():
|
||||
journal.reserve(binding)
|
||||
results.put('admitted')
|
||||
except Refused:
|
||||
results.put('refused')
|
||||
finally:
|
||||
journal.close()
|
||||
|
||||
|
||||
class Tests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tmp = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(self.tmp.cleanup)
|
||||
self.path = Path(self.tmp.name)
|
||||
self.binding = Binding('approval-1', 'a'*64, str(uuid.uuid4()), 'b'*64)
|
||||
self.journal = Journal(self.path)
|
||||
self.addCleanup(self.journal.close)
|
||||
|
||||
def test_actual_multi_process_race_admits_once(self):
|
||||
context = multiprocessing.get_context('fork')
|
||||
gate, results = context.Event(), context.Queue()
|
||||
workers = [context.Process(target=reserve_worker,args=(str(self.path),self.binding,gate,results)) for _ in range(4)]
|
||||
for w in workers: w.start()
|
||||
gate.set()
|
||||
for w in workers:
|
||||
w.join(10)
|
||||
if w.is_alive(): w.terminate(); w.join(); self.fail('worker exceeded bound')
|
||||
self.assertEqual(w.exitcode, 0)
|
||||
self.assertEqual(sorted(results.get(timeout=2) for _ in workers), ['admitted','refused','refused','refused'])
|
||||
|
||||
def test_reservation_persists_after_process_abandonment(self):
|
||||
with self.journal.locked(): self.journal.reserve(self.binding)
|
||||
reopened = Journal(self.path)
|
||||
try:
|
||||
self.assertEqual(reopened.observe(self.binding)['state'], 'reserved')
|
||||
self.assertFalse(reopened.observe(self.binding)['dispatch_allowed'])
|
||||
with reopened.locked():
|
||||
with self.assertRaises(Refused): reopened.reserve(self.binding)
|
||||
with self.assertRaises(Refused): reopened.transition(self.binding,'reserved','consume-confirmed')
|
||||
finally: reopened.close()
|
||||
|
||||
def test_same_approval_different_digest_refused(self):
|
||||
with self.journal.locked(): self.journal.reserve(self.binding)
|
||||
changed = Binding('approval-1','c'*64,str(uuid.uuid4()),'b'*64)
|
||||
with self.journal.locked():
|
||||
with self.assertRaises(Refused): self.journal.reserve(changed)
|
||||
with self.assertRaises(Refused): self.journal.observe(changed)
|
||||
|
||||
def test_same_operation_different_approval_refused(self):
|
||||
with self.journal.locked(): self.journal.reserve(self.binding)
|
||||
with self.journal.locked():
|
||||
with self.assertRaises(Refused): self.journal.reserve(Binding('approval-2','a'*64,self.binding.operation_id,'b'*64))
|
||||
|
||||
def test_full_path_cleanup_and_terminal_replay(self):
|
||||
states=['reserved','consume-confirmed','authenticating','grant-issuing','grant-issued','applying','readback','verified','cleanup-confirmed']
|
||||
with self.journal.locked():
|
||||
self.journal.reserve(self.binding)
|
||||
for before,after in zip(states,states[1:]):
|
||||
self.journal.transition(self.binding,before,after,'c'*64)
|
||||
with self.assertRaises(Refused): self.journal.transition(self.binding,'cleanup-confirmed','applying')
|
||||
self.assertEqual(self.journal.observe(self.binding),{'state':'cleanup-confirmed','evidence_digest':'c'*64,'dispatch_allowed':False,'external_outcome_unknown':False})
|
||||
with self.journal.locked():
|
||||
with self.assertRaises(Refused): self.journal.reserve(self.binding)
|
||||
|
||||
def test_unknown_is_terminal(self):
|
||||
with self.journal.locked():
|
||||
self.journal.reserve(self.binding)
|
||||
self.journal.transition(self.binding,'reserved','unknown')
|
||||
with self.assertRaises(Refused): self.journal.transition(self.binding,'unknown','reserved')
|
||||
|
||||
def test_early_dispatch_wrong_state_and_cleanup_without_evidence_refused(self):
|
||||
with self.journal.locked():
|
||||
self.journal.reserve(self.binding)
|
||||
with self.assertRaises(Refused): self.journal.transition(self.binding,'reserved','applying')
|
||||
with self.assertRaises(Refused): self.journal.transition(self.binding,'consume-confirmed','authenticating')
|
||||
self.assertEqual(self.journal.observe(self.binding)['state'],'reserved')
|
||||
|
||||
def test_other_live_invocation_cannot_obtain_lock(self):
|
||||
second=Journal(self.path)
|
||||
try:
|
||||
with self.journal.locked():
|
||||
with self.assertRaises(Refused):
|
||||
with second.locked(): pass
|
||||
finally: second.close()
|
||||
|
||||
def test_symlink_and_hardlink_files_refused(self):
|
||||
for name,link in [('journal.sqlite','hard'),('execution.lock','symbolic')]:
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
p=Path(d); target=p/'other'; target.touch(mode=0o600)
|
||||
if link=='hard': os.link(target,p/name)
|
||||
else: (p/name).symlink_to(target)
|
||||
with self.assertRaises((Refused,OSError)): Journal(p)
|
||||
|
||||
def test_nonprivate_directory_refused(self):
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
os.chmod(d,0o755)
|
||||
with self.assertRaises(Refused): Journal(Path(d))
|
||||
|
||||
def test_binding_rejects_unbounded_or_malformed_metadata(self):
|
||||
for value in ['token'+ 'x'*200, '../approval', 'approval\n1']:
|
||||
with self.assertRaises(Refused): Binding(value,'a'*64,self.binding.operation_id,'b'*64).validate()
|
||||
for value in ['a'*63,'A'*64,'not-a-digest']:
|
||||
with self.assertRaises(Refused): Binding('a',value,self.binding.operation_id,'b'*64).validate()
|
||||
|
||||
def test_pending_external_call_blocks_next_and_survives_reopen(self):
|
||||
with self.journal.locked():
|
||||
self.journal.reserve(self.binding)
|
||||
self.journal.before_call(self.binding,0,'d'*64)
|
||||
with self.assertRaises(Refused): self.journal.before_call(self.binding,1,'e'*64)
|
||||
with self.assertRaises(Refused): self.journal.transition(self.binding,'reserved','consume-confirmed')
|
||||
reopened=Journal(self.path)
|
||||
try:
|
||||
self.assertTrue(reopened.observe(self.binding)['external_outcome_unknown'])
|
||||
self.assertFalse(reopened.observe(self.binding)['dispatch_allowed'])
|
||||
finally: reopened.close()
|
||||
|
||||
def test_call_order_and_exact_confirmation(self):
|
||||
with self.journal.locked():
|
||||
self.journal.reserve(self.binding)
|
||||
with self.assertRaises(Refused): self.journal.before_call(self.binding,1,'d'*64)
|
||||
self.journal.before_call(self.binding,0,'d'*64)
|
||||
with self.assertRaises(Refused): self.journal.after_call(self.binding,0,'e'*64,'f'*64)
|
||||
self.journal.after_call(self.binding,0,'d'*64,'f'*64)
|
||||
with self.assertRaises(Refused): self.journal.after_call(self.binding,0,'d'*64,'f'*64)
|
||||
with self.assertRaises(Refused): self.journal.before_call(self.binding,0,'d'*64)
|
||||
self.journal.before_call(self.binding,1,'e'*64)
|
||||
|
||||
def test_nonstring_binding_and_boolean_ordinal_refused(self):
|
||||
with self.assertRaises(Refused): Binding(True,'a'*64,self.binding.operation_id,'b'*64).validate()
|
||||
with self.journal.locked():
|
||||
self.journal.reserve(self.binding)
|
||||
with self.assertRaises(Refused): self.journal.before_call(self.binding,False,'d'*64)
|
||||
|
||||
def test_confirmation_rejects_sqlite_ordinal_coercion(self):
|
||||
with self.journal.locked():
|
||||
self.journal.reserve(self.binding)
|
||||
self.journal.before_call(self.binding,0,'d'*64)
|
||||
for ordinal in (False,0.0,'0',None,-1,64):
|
||||
with self.subTest(ordinal=ordinal):
|
||||
with self.assertRaises(Refused): self.journal.after_call(self.binding,ordinal,'d'*64,'f'*64)
|
||||
self.assertTrue(self.journal.observe(self.binding)['external_outcome_unknown'])
|
||||
for digest in (None,False,'D'*64,'d'*63):
|
||||
with self.assertRaises(Refused): self.journal.after_call(self.binding,0,digest,'f'*64)
|
||||
self.assertTrue(self.journal.observe(self.binding)['external_outcome_unknown'])
|
||||
self.journal.after_call(self.binding,0,'d'*64,'f'*64)
|
||||
self.assertFalse(self.journal.observe(self.binding)['external_outcome_unknown'])
|
||||
|
||||
if __name__=='__main__': unittest.main()
|
||||
|
|
@ -990,6 +990,7 @@ none of the ordinary generic lifecycle outcomes.
|
|||
id: RPF-WP-0035-T13
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "8f6966fa-6e9a-58b2-8b40-c47340ec19d1"
|
||||
```
|
||||
|
||||
2026-10-11: Platform agent loaded its owner instructions/INTENT and RPF35-T02,
|
||||
|
|
@ -1023,3 +1024,57 @@ before the formal v5 exact source review. V4 changes-requested review and earlie
|
|||
failed history remain retained, with no native success, inherited grant or scope
|
||||
promotion. Actual private producer admission, fresh installed role/leeway/policy
|
||||
observation, authenticated founder window and native refusal/cleanup remain gates.
|
||||
|
||||
|
||||
2026-10-11 T11 journal preparation refinement (source-only): independently
|
||||
inspected frozen root-maker v2 manifest
|
||||
`341cac1de945d2fbe8f516119909bd44fc37e85dccfb38b451981d4de2d402e7`,
|
||||
verified all input hashes, and ran14 supplied tests plus5 independent checks.
|
||||
The actual four-process race admits once; a separately forked process exiting
|
||||
immediately after pending intent leaves durable unknown/nonresumable state.
|
||||
Private SQLite modes, lock admission and binding/replay protections remain guarded.
|
||||
Three independent counterexamples show after_call accepts False,0.0 or text'0'
|
||||
as persisted integer ordinal0, contrary to before_call's exact integer validation.
|
||||
Completed preparation under this existing done ownerT11 record precedes formal
|
||||
review; require identical ordinal/call-digest validation before confirmation so
|
||||
malformed calls cannot clear pending outcome. RPF35-T12 retains caller/PDP/consume
|
||||
validation, exact body compiler/adapter and owner-private cleanup/recovery after
|
||||
unknown; this unintegrated primitive proves none of those or full contract/native
|
||||
acceptance. Inputs/prior reviews are preserved; no privileged/native action occurred.
|
||||
|
||||
|
||||
2026-10-11 T11 journal v3 correction preparation (same trial): frozen manifest
|
||||
`905ff6666d05df6a19d165a535579d917d7de31a43e066c2afc34a57e8cbdc9d`
|
||||
verified against every file. Strict after_call integer0..63 and64hex string digest
|
||||
validation now precedes SQLite confirmation; False,0.0 or text'0' cannot clear
|
||||
pending external outcome.15 supplied tests plus5 independent regressions pass,
|
||||
including realfork abrupt exit after durable intent and privatefile checks.
|
||||
This existing completed ownerT11 refinement precedes the formal corrected-source
|
||||
review. Prior v2 refusal is retained; no extra success/authority trial is counted.
|
||||
Acceptance is only unintegrated journal source. Actual caller/PDP/consume validation,
|
||||
independently compiled body/ordinal plan, restricted adapter, owner-private unknown
|
||||
cleanup recovery and native/whole-contract adoption remain live RPF35-T12 gates.
|
||||
|
||||
|
||||
2026-10-11 T13 node-route source preparation refinement (same trial): exact
|
||||
successor manifest `23a972abc5175e121e594726d2b7f7a28c62109253f58f12623eaf2e5564a035`
|
||||
verified against all entries. Platform Service openbao-ui-gateway8080 and its
|
||||
nginx /v1 proxy agree with the proposed bounded founder-held node port-forward;
|
||||
workstation tunnel/DNS assumptions are not reused as node evidence.54 supplied
|
||||
lifecycle/route checks plus6 independent public-health/abort checks pass, offline.
|
||||
Initial execute/recovery health pin and repeated pre-create check fail before
|
||||
native/Secret effects; public-preflight reads neither stdin nor Kubernetes.
|
||||
Completed ownT13 preparation precedes this fresh exact source review, not reuse
|
||||
of v5 acknowledgment. Main execute currently reads private stdin before execute's
|
||||
health gate; the packet's pre-token-input phrase is not accepted. Private producer
|
||||
handoff must preserve actual ordering or move the health gate before credential
|
||||
input when implemented. Public cluster digest detects drift, not authenticated
|
||||
estate identity. No route was opened or observed; no source packet authenticates
|
||||
a founder approval. Native role/plugin version and raw/effective expiration,
|
||||
clock-skew and not-before leeways require actual owner observation/semantic proof.
|
||||
Issuer readiness_state/Argo ownership is not established by the inspected source;
|
||||
unmapped means production-tier. If adopted/production-approved, temporary direct
|
||||
CAS requires an explicit reviewed one-use maintenance exception and close-down
|
||||
entry, plus reconciliation, before native go. No helper/source acknowledgment
|
||||
waives that gate. Private token producer/callback/client/custody admission and
|
||||
actual native negative/revoke/restoration/cleanup remain prerequisites.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue