docs: preserve reviewed NetKingdom session artifacts
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 2s
Reject generated-only commits / generated-commit-guard (push) Successful in 25s

This commit is contained in:
codex 2026-11-01 22:45:01 +01:00
parent b77ad96bd5
commit 3add9f8790
45 changed files with 16252 additions and 0 deletions

View file

@ -0,0 +1,46 @@
## 2026-10-16 workload-only candidate lock and actual-manager preparation
Prepared under existing REINAH-WP-0008-T07 / GLAS-WP-0012 acceptance work.
The combined-runtime lock still selects Glas `30be8180`, so the rebuilt
`818b1b7c` artifact cannot include published workload-only delivery `7357115c`.
The prepared lock-only patch advances that dependency; llm-connect `37436bb5`
and sandboxer `221126cb` remain pinned to the prior admitted source set. Rein
source is `be5ef400`; an isolated preparation commit `c811fc43` contains the
patch. This isolated commit is not an owner publication.
The existing owner builder produced candidate runtime
`634e65fee5517ebee0d1080805fd84c81bd46af26a2b38ec1ab14bd2be17bf8f`, using the
same native Claude 2.1.266 binary (`19842705…`), frozen uv.lock and source-content
verification. The runtime is only in `/tmp/netkingdom-runtime-next-20261016/runtime`.
Canonical owner repositories, retained artifact pins and native owner
configuration were not changed by this preparation.
All 141 Glas tests and seven rein runtime-lock/rehearsal tests pass. The complete
runtime digest recomputed after all proofs remains `634e65fee5517…`. Using the candidate's installed packages, the actual
SandboxManager and Glas gateway execute the unchanged
`harness.agent-dev-local@1.1.1` profile (still `unverified`): real rein/Glas CLI
startup, Claude --version, read-only artifact, absent synthetic host file,
inherited environment and child-process denial, exact task identity/private
state, deterministic Git effect in the disposable workspace, task removal and
manager destruction pass. A separately labelled synthetic route fixture proves
only the explicit workload receives its synthetic provider value, output is
redacted, every housekeeping command has empty routes and the following command
is clean. Real manager refusals for wrong actor/project/run, expired execution,
expiry cleanup, explicit cancellation and post-cancellation execution also pass.
No model, provider request, real credential read or spend occurred.
First proof attempt correctly encountered PermissionError on wrong consumer but
the proof runner expected only ValueError/RuntimeError. Its finally cleanup ran;
the runner was amended, with the failed attempt preserved in proof-attempts.json.
The artifact was unchanged. This is a refined test attempt, not a new unchanged
execution success.
Owner review/integration of the lock patch must produce an owner source revision
and a rebuilt artifact whose complete digest is verified again. Candidate
preparation does not authorize native installation or admission. T07's queued
spend memo, native artifact installation/rehearsal, renewal and file-pin updates,
required approvals and bounded real-model/tool proof remain open. GLAS native
acceptance and actual interactive assignment migration, denied external tool
paths, bounded delegation and revocation remain open; no readiness or supervision
promotion is inferred. Older `818b1b7c`, `ee3d0a53`, installed `b6e4e8a4` and their
failed/unknown outcomes remain historical evidence.

View file

@ -0,0 +1,31 @@
{
"attempts": [
{
"attempt": 1,
"outcome": "proof-runner-exception",
"gateway_proof_completed": true,
"failure": "Manager correctly refused mismatched consumer with PermissionError; runner expected ValueError or RuntimeError",
"recovery": "Fixture finally destroyed sandbox. Runner catch amended to include PermissionError. Artifact unchanged.",
"unchanged_success": false
},
{
"attempt": 2,
"outcome": "passed",
"scope": "exact unmodified1.1.1 gateway + manager identity/expiry/cancellation",
"artifact_unchanged": true
},
{
"attempt": 3,
"outcome": "passed",
"scope": "same exact profile + separately labelled synthetic credential route gateway fixture + manager lifecycle",
"artifact_unchanged": true
},
{
"attempt": 4,
"outcome": "passed",
"scope": "canonical published rein9b88cad artifact f59959b6, unchanged1.1.1 gateway and separate synthetic route fixture plus manager lifecycle",
"refinement_from_attempt1_retained": true,
"native_acceptance": false
}
]
}

View file

@ -0,0 +1,13 @@
diff --git a/deploy/runtime-contract-lock.json b/deploy/runtime-contract-lock.json
index ee804ca..2ef3087 100644
--- a/deploy/runtime-contract-lock.json
+++ b/deploy/runtime-contract-lock.json
@@ -13,7 +13,7 @@
"version": "0.1.0"
},
{
- "commit": "30be81808140a3a3d137e731d1fe9aed59ad8581",
+ "commit": "7357115c8311e55ee3d495f5266f501a17ec3c89",
"distribution": "glas-harness",
"source": "../glas-harness",
"version": "0.1.0"

View file

@ -0,0 +1,2 @@
....... [100%]
7 passed in 0.59s

View file

@ -0,0 +1,24 @@
{
"dependencies": [
{
"clean": true,
"commit": "37436bb562a3f20abc3b88defc5bae6508c32e7e",
"distribution": "llm-connect",
"version": "0.1.0"
},
{
"clean": true,
"commit": "7357115c8311e55ee3d495f5266f501a17ec3c89",
"distribution": "glas-harness",
"version": "0.1.0"
},
{
"clean": true,
"commit": "221126cb77ea41ec283598a23d628f760a51bdea",
"distribution": "sandboxer",
"version": "0.0.0"
}
],
"ok": true,
"schema_version": "1"
}

View file

@ -0,0 +1,7 @@
{
"rein-aharness": "be5ef400861a5e31a31f29d173990c7a143fb189",
"glas-harness": "7357115c8311e55ee3d495f5266f501a17ec3c89",
"llm-connect": "37436bb562a3f20abc3b88defc5bae6508c32e7e",
"sand-boxer": "221126cb77ea41ec283598a23d628f760a51bdea",
"candidate_rein": "c811fc430f80e214b43cfcca5dc9e7f786d5f559"
}

View file

@ -0,0 +1,69 @@
# Glas owner implementation — 16 October 2026
Prepared a concrete source patch in an isolated copy of current tracked Glas
files, retaining working-tree contents. Canonical Glas/Sand-boxer/rein sources,
profiles, native policies, installed artifacts and supervision authority were
not modified. Dirty Glas `.custodian-brief.md` and `WORK-RECORDS.md` are preserved.
The gateway previously requested profile credential routes for every owner
command, including executable lookup, task writers/removers, Git helpers and
artifact probes. The patch gives housekeeping an empty-route binding and gives
only explicit rein workload execution the profile routes. Both concrete adapters
use the explicit path. Missing workload binding refuses; an SSH selection with
credential routes refuses instead of silently bypassing owner delivery. This
narrows trusted gateway behavior, not arbitrary caller authorization.
Selected `harness.agent-dev-local@1.1.1` already has empty credential refs and
uses the rein's task-scoped MessagesOwner route outside bwrap. This patch does
not revoke that route or claim its scoped capability is an admin credential.
It prevents future/raw provider route selections from granting housekeeping
provider values. No generic shell broker or supervisor service was added.
Validation:
- All 141 Glas tests pass; regression checks cover exact create-time identity,
timeout and stdin, empty housekeeping routes, explicit workload routes,
missing binding refusal and remote credential refusal.
- Actual disposable bwrap through Glas transport proves a synthetic host
credential file absent, inherited BAO/VAULT/AWS/SSH variables denied including
a child subprocess, provider value only in the explicit workload, output
redaction, no subsequent-command value, and workspace destruction.
- `git apply --check` passes against canonical Glas. No provider/model call,
real credential read, remote live execution or spend occurred.
Artifacts: [patch](glas-harness.patch), [source hashes](source-manifest.json),
[test result](tests.json), [actual bwrap proof](bwrap-proof.json),
[patch check](patch-check.json). Patch SHA-256:
`83eeeb0017603aabae0ff49a23f96248f677f6c9f3e2c01b22f6d0416fca69c7`.
The reproducible proof source is included in the patch. The isolated source
remains `/tmp/netkingdom-agent-isolation-20261016/glas-harness`.
## Exact native gates retained
1. Review/apply this owner patch and reconcile its resulting runtime/source pins.
Do not reuse an admitted artifact digest for changed contents. The patch adds
a dated preparation note to GLAS-WP-0012 without completing a native task.
2. Latest dependency sources supersede historical missing-key/lane accounts:
September 27 native lanes were applied, verified and revoked. The corrected
owner runtime `818b1b7c…` was rebuilt October 15 and passes no-credential
startup; it is not installed/admitted on Railiance (still `b6e4e8a4…`).
3. REINAH-WP-0008-T07 retains queued spend memo lifecycle acceptance (workspace
`2ccb4bda-e318-51d2-a8dd-709db768494f`, review
`review-e2d2e98f-4701-45b0-abc1-4fe9f00bd1a8`), owner artifact installation,
`metered-once --rehearse`, owner renewal and Secrets Engine file-pin updates,
required native approvals, then successful bounded model/tool/commit proof.
Previously consumed approvals are historical evidence, not reusable authority.
4. GLAS-WP-0012-T02–T05 remain subject to accepted runtime/profile and combined
actual rein/model/task cleanup proof. The standalone bwrap proof establishes
none of those model/provider outcomes.
5. CUST-WP-0073-T02/T04 and TSA-06 additionally require admission of this actual
interactive agent assignment: its host files/mounts/env/subprocesses and
external tool paths must lose admin authority, with scoped distinguishable
task identity, revocation/expiry/cancellation and bounded delegation evidence.
The current interactive runtime has not moved into this disposable sandbox.
The assignment supervision record remains supervised, authority_granted false;
this owner worker does not approve a privileged path or promote the agent.
No task status, profile readiness, CUST-WP-0073 completion or TSA-06 acceptance
is inferred from the patch or synthetic proof. The stated owner/native gates
remain live in existing workplans; source delivery is separate from admission.

View file

@ -0,0 +1,21 @@
{
"exit_code": 0,
"result": {
"scope": "disposable bwrap via Glas transport; not interactive assignment",
"model_calls": 0,
"real_credentials_read": false,
"host_file_denied": true,
"inherited_env_and_subprocess_denied": true,
"credential_routes_by_command": [
[],
[
"synthetic"
],
[]
],
"provider_output_redacted": true,
"subsequent_command_clean": true,
"workspace_removed": true
},
"stderr": ""
}

View file

@ -0,0 +1,464 @@
--- a/src/glas_harness/contract.py
+++ b/src/glas_harness/contract.py
@@ -117,6 +117,8 @@
class SandboxHandle(ContractModel):
# Process-local owner binding; never serialized as reachability or evidence.
_owner_execute: Any = PrivateAttr(default=None)
+ _owner_workload_execute: Any = PrivateAttr(default=None)
+ _credential_route_refs: list[str] = PrivateAttr(default_factory=list)
_timeout_seconds: int = PrivateAttr(default=600)
sandbox_id: str
--- a/src/glas_harness/gateway.py
+++ b/src/glas_harness/gateway.py
@@ -7,6 +7,7 @@
from __future__ import annotations
import time
+from functools import partial
from collections.abc import Callable
import uuid
from datetime import UTC, datetime
@@ -145,19 +146,23 @@
reachability=reachability,
)
- def owner_execute(argv, input_text, timeout):
+ def owner_execute(argv, input_text, timeout, *, credential_routes=()):
return manager.execute(
sandbox.sandbox_id,
SandboxExecRequest(
command=list(argv),
consumer=consumer,
- credential_route_refs=profile.credential_route_refs,
+ credential_route_refs=list(credential_routes),
stdin_text=input_text,
timeout_seconds=timeout,
),
)
sandbox._owner_execute = owner_execute
+ sandbox._owner_workload_execute = partial(
+ owner_execute, credential_routes=tuple(profile.credential_route_refs)
+ )
+ sandbox._credential_route_refs = list(profile.credential_route_refs)
sandbox._timeout_seconds = profile.limits.timeout_seconds or 600
session = selected_rein.start_session(
--- a/src/glas_harness/transport.py
+++ b/src/glas_harness/transport.py
@@ -13,7 +13,7 @@
import shlex
import subprocess
import uuid
-from dataclasses import dataclass
+from dataclasses import dataclass, replace
from pathlib import Path, PurePosixPath
from typing import Any, Callable, Literal, Sequence
@@ -36,6 +36,7 @@
pid: int | None = None
ssh_target: str | None = None
owner_execute: Callable | None = None
+ owner_workload_execute: Callable | None = None
timeout_seconds: int = 600
def command(self, argv: Sequence[str]) -> list[str]:
@@ -94,6 +95,26 @@
timeout=bounded_timeout,
)
+ def run_workload(
+ self,
+ argv: Sequence[str],
+ *,
+ input_text: str | None = None,
+ timeout: float | None = None,
+ ) -> subprocess.CompletedProcess[str]:
+ """Run the selected rein; only this path requests provider routes.
+
+ The gateway is trusted control-plane code. This separation narrows its
+ credential delivery; it is not authentication of arbitrary Python callers.
+ """
+ if self.kind == "local_namespace":
+ if self.owner_workload_execute is None:
+ raise TransportError("workload requires an owner workload binding")
+ return replace(self, owner_execute=self.owner_workload_execute).run(
+ argv, input_text=input_text, timeout=timeout
+ )
+ return self.run(argv, input_text=input_text, timeout=timeout)
+
def resolve_executable(self, name: str, *, timeout: float = 15.0) -> str:
if not name or "/" in name:
raise TransportError("rein executable must be a command name, not a host path")
@@ -169,9 +190,12 @@
return ExecutionTransport(
kind="local_namespace", workspace=str(workspace), pid=parsed_pid,
owner_execute=sandbox._owner_execute,
+ owner_workload_execute=sandbox._owner_workload_execute,
timeout_seconds=sandbox._timeout_seconds,
)
if has_remote:
+ if sandbox._credential_route_refs:
+ raise TransportError("SSH transport has no owner credential delivery contract")
if not ssh_target or not remote_dir:
raise TransportError(
"incomplete remote sandbox reachability: ssh and remote_dir are required"
--- a/src/glas_harness/reins/rein_aharness.py
+++ b/src/glas_harness/reins/rein_aharness.py
@@ -109,7 +109,7 @@
argv += ["--tool-profile", self.tool_profile]
if self.budget_tokens:
argv += ["--budget-tokens", str(self.budget_tokens)]
- proc = transport.run(argv, timeout=session["timeout_seconds"])
+ proc = transport.run_workload(argv, timeout=session["timeout_seconds"])
ok = proc.returncode == 0
output, events = self._split_stream_events(proc.stdout)
last_result = session["last_result"] = parse_json_object(output)
--- a/src/glas_harness/reins/rein_openweights.py
+++ b/src/glas_harness/reins/rein_openweights.py
@@ -91,7 +91,7 @@
argv += ["--budget-tokens", str(self.budget_tokens)]
if self.tool_profile:
argv += ["--tool-profile", self.tool_profile]
- proc = transport.run(argv, timeout=session["timeout_seconds"])
+ proc = transport.run_workload(argv, timeout=session["timeout_seconds"])
ok = proc.returncode == 0
last_result = session["last_result"] = parse_json_object(proc.stdout)
return ToolResult(
--- a/tests/test_gateway.py
+++ b/tests/test_gateway.py
@@ -150,6 +150,7 @@
assert "_owner_execute" not in sandbox.model_dump()
transport = transport_from_sandbox(sandbox)
transport.run(["printf", "%s", "non-secret"], timeout=30)
+ transport.run_workload(["rein-aharness", "run"], timeout=30)
path = transport.write_task_file({"title": "private prompt"})
transport.remove_file(path)
return super().start_session(profile, inputs, sandbox)
@@ -164,14 +165,14 @@
assert create_consumer.project == "exact-project"
assert create_consumer.run_id == result.evidence.request_id
assert create_consumer.session_id is None
- assert manager.execute.call_count == 3
+ assert manager.execute.call_count == 4
for call in manager.execute.call_args_list:
sandbox_id, command = call.args
assert sandbox_id == "sbx1"
assert command.consumer == create_consumer
- assert command.credential_route_refs == refs
+ assert command.credential_route_refs == (refs if command.command[0] == "rein-aharness" else [])
assert command.timeout_seconds == 7
- writer = manager.execute.call_args_list[1].args[1]
+ writer = manager.execute.call_args_list[2].args[1]
assert writer.stdin_text == '{"title": "private prompt"}'
assert "private prompt" not in str(writer.command)
manager.destroy.assert_called_once_with("sbx1")
--- a/tests/test_transport.py
+++ b/tests/test_transport.py
@@ -173,3 +173,16 @@
):
with pytest.raises(TransportError, match="inside the selected sandbox"):
transport.git_head()
+
+
+def test_workload_refuses_missing_dedicated_owner_binding():
+ transport = ExecutionTransport(kind="local_namespace", workspace="/work", owner_execute=lambda *args: None)
+ with pytest.raises(TransportError, match="workload binding"):
+ transport.run_workload(["true"])
+
+
+def test_remote_transport_refuses_requested_credential_routes():
+ sandbox = SandboxHandle(sandbox_id="remote", host="remote", reachability={"ssh":"agent@host", "remote_dir":"/work"})
+ sandbox._credential_route_refs = ["provider-route"]
+ with pytest.raises(TransportError, match="credential delivery"):
+ transport_from_sandbox(sandbox)
--- a/tests/test_rein_aharness.py
+++ b/tests/test_rein_aharness.py
@@ -80,18 +80,18 @@
budget_tokens=1234,
)
transport = MagicMock(spec=ExecutionTransport)
- transport.run.return_value = MagicMock(returncode=0, stdout="ok", stderr="")
- session = {"task_file": "/tmp/task.json", "transport": transport, "timeout_seconds": 30}
-
- with patch.object(rein, "_bin", return_value="/usr/bin/agent-harness"):
- result = rein.dispatch_tool(session, ToolCall(name="run_task"))
-
- argv = transport.run.call_args.args[0]
+ transport.run_workload.return_value = MagicMock(returncode=0, stdout="ok", stderr="")
+ session = {"task_file": "/tmp/task.json", "transport": transport, "timeout_seconds": 30}
+
+ with patch.object(rein, "_bin", return_value="/usr/bin/agent-harness"):
+ result = rein.dispatch_tool(session, ToolCall(name="run_task"))
+
+ argv = transport.run_workload.call_args.args[0]
assert argv[:3] == ["/usr/bin/agent-harness", "run", "--task-file"]
assert argv[argv.index("--model") + 1] == "claude-sonnet-4-6"
assert argv[argv.index("--tool-profile") + 1] == "green-commit-only"
assert argv[argv.index("--budget-tokens") + 1] == "1234"
- assert transport.run.call_args.kwargs["timeout"] == 30
+ assert transport.run_workload.call_args.kwargs["timeout"] == 30
assert result.ok is True
assert result.output == "ok"
@@ -99,7 +99,7 @@
def test_dispatch_tool_reports_failure() -> None:
rein = ReinAharness()
transport = MagicMock(spec=ExecutionTransport)
- transport.run.return_value = MagicMock(returncode=1, stdout="", stderr="boom")
+ transport.run_workload.return_value = MagicMock(returncode=1, stdout="", stderr="boom")
session = {"task_file": "/tmp/task.json", "transport": transport, "timeout_seconds": 30}
with patch.object(rein, "_bin", return_value="/usr/bin/agent-harness"):
@@ -167,14 +167,14 @@
json.dumps({"stream_event": {"type": "system", "subtype": "hook_started"}}),
json.dumps({"ok": True, "committed": True}, indent=2),
]
- transport.run.return_value = MagicMock(
+ transport.run_workload.return_value = MagicMock(
returncode=0, stdout="\n".join(stdout_lines), stderr=""
)
with patch.object(rein, "_bin", return_value="/usr/bin/agent-harness"):
result = rein.dispatch_tool(session, ToolCall(name="run_task"))
- argv = transport.run.call_args.args[0]
+ argv = transport.run_workload.call_args.args[0]
assert "--stream-tool-events" in argv
assert len(result.events) == 2
assert result.events[0]["message"]["content"][0]["name"] == "Read"
@@ -186,13 +186,13 @@
def test_dispatch_tool_no_stream_flag_by_default() -> None:
rein = ReinAharness()
transport = MagicMock(spec=ExecutionTransport)
- transport.run.return_value = MagicMock(returncode=0, stdout="ok", stderr="")
- session = {"task_file": "/tmp/task.json", "transport": transport, "timeout_seconds": 30}
-
- with patch.object(rein, "_bin", return_value="/usr/bin/agent-harness"):
- result = rein.dispatch_tool(session, ToolCall(name="run_task"))
-
- argv = transport.run.call_args.args[0]
+ transport.run_workload.return_value = MagicMock(returncode=0, stdout="ok", stderr="")
+ session = {"task_file": "/tmp/task.json", "transport": transport, "timeout_seconds": 30}
+
+ with patch.object(rein, "_bin", return_value="/usr/bin/agent-harness"):
+ result = rein.dispatch_tool(session, ToolCall(name="run_task"))
+
+ argv = transport.run_workload.call_args.args[0]
assert "--stream-tool-events" not in argv
assert result.events == []
@@ -235,7 +235,7 @@
payload = {"ok": True}
if reported is not None:
payload["model"] = reported
- transport.run.return_value = MagicMock(returncode=0, stdout=json.dumps(payload), stderr="")
+ transport.run_workload.return_value = MagicMock(returncode=0, stdout=json.dumps(payload), stderr="")
transport.git_head.return_value = "new-head"
session = {"task_file": "/tmp/task.json", "transport": transport,
"timeout_seconds": 30, "head_before": "old-head"}
--- a/tests/test_rein_openweights.py
+++ b/tests/test_rein_openweights.py
@@ -76,13 +76,13 @@
def test_dispatch_tool_invokes_rein_openweights_cli() -> None:
rein = ReinOpenWeights()
transport = MagicMock(spec=ExecutionTransport)
- transport.run.return_value = MagicMock(returncode=0, stdout="ok", stderr="")
+ transport.run_workload.return_value = MagicMock(returncode=0, stdout="ok", stderr="")
session = {"task_file": "/tmp/task.json", "transport": transport, "timeout_seconds": 30}
with patch.object(rein, "_bin", return_value="/usr/bin/rein-openweights"):
result = rein.dispatch_tool(session, ToolCall(name="run_task"))
- argv = transport.run.call_args.args[0]
+ argv = transport.run_workload.call_args.args[0]
assert argv[:3] == ["/usr/bin/rein-openweights", "run", "--task-file"]
assert "--no-hub" in argv
assert result.ok is True
@@ -97,13 +97,13 @@
tool_profile="green-commit-only",
)
transport = MagicMock(spec=ExecutionTransport)
- transport.run.return_value = MagicMock(returncode=0, stdout="ok", stderr="")
+ transport.run_workload.return_value = MagicMock(returncode=0, stdout="ok", stderr="")
session = {"task_file": "/tmp/task.json", "transport": transport, "timeout_seconds": 30}
with patch.object(rein, "_bin", return_value="/usr/bin/rein-openweights"):
rein.dispatch_tool(session, ToolCall(name="run_task"))
- argv = transport.run.call_args.args[0]
+ argv = transport.run_workload.call_args.args[0]
assert "--model" in argv
assert "meta-llama/llama-3.1-70b-instruct" in argv
assert argv[argv.index("--max-turns") + 1] == "8"
@@ -114,7 +114,7 @@
def test_dispatch_tool_reports_failure() -> None:
rein = ReinOpenWeights()
transport = MagicMock(spec=ExecutionTransport)
- transport.run.return_value = MagicMock(returncode=1, stdout="", stderr="boom")
+ transport.run_workload.return_value = MagicMock(returncode=1, stdout="", stderr="boom")
session = {"task_file": "/tmp/task.json", "transport": transport, "timeout_seconds": 30}
with patch.object(rein, "_bin", return_value="/usr/bin/rein-openweights"):
@@ -127,7 +127,7 @@
def test_dispatch_tool_enforces_outer_timeout() -> None:
rein = ReinOpenWeights()
transport = MagicMock(spec=ExecutionTransport)
- transport.run.side_effect = subprocess.TimeoutExpired("rein-openweights", 30)
+ transport.run_workload.side_effect = subprocess.TimeoutExpired("rein-openweights", 30)
session = {
"task_file": "/tmp/task.json",
"transport": transport,
@@ -138,7 +138,7 @@
with pytest.raises(subprocess.TimeoutExpired):
rein.dispatch_tool(session, ToolCall(name="run_task"))
- assert transport.run.call_args.kwargs["timeout"] == 30
+ assert transport.run_workload.call_args.kwargs["timeout"] == 30
def test_end_session_detects_new_commit(tmp_path) -> None:
@@ -183,7 +183,7 @@
payload = {"ok": True}
if reported is not None:
payload["model"] = reported
- transport.run.return_value = MagicMock(returncode=0, stdout=json.dumps(payload), stderr="")
+ transport.run_workload.return_value = MagicMock(returncode=0, stdout=json.dumps(payload), stderr="")
transport.git_head.return_value = "new-head"
session = {"task_file": "/tmp/task.json", "transport": transport,
"timeout_seconds": 30, "head_before": "old-head"}
--- a/tests/test_rein_session_isolation.py
+++ b/tests/test_rein_session_isolation.py
@@ -19,7 +19,7 @@
transport = MagicMock(spec=ExecutionTransport)
transport.resolve_executable.return_value = "/runtime/rein"
transport.git_head.return_value = f"head-{index}"
- transport.run.return_value = MagicMock(returncode=0 if ok else 1, stderr="",
+ transport.run_workload.return_value = MagicMock(returncode=0 if ok else 1, stderr="",
stdout=json.dumps({"ok": ok, "tokens_spent": 10 + index,
"model": f"model-{index}", "reason": None if ok else "failed"}))
sessions.append({"transport": transport, "task_file": f"/workspace-{index}/task",
--- /dev/null
+++ b/scripts/prove-credential-command-scope.py
@@ -0,0 +1,55 @@
+"""No model/provider: actual bwrap transport proof with synthetic credentials."""
+import json
+import os
+import sys
+import tempfile
+from pathlib import Path
+from sandboxer.extensions.bwrap import BwrapExtension
+from sandboxer.models import Profile
+from glas_harness.contract import SandboxHandle
+from glas_harness.transport import transport_from_sandbox
+
+
+def main():
+ with tempfile.TemporaryDirectory(prefix="glas-command-scope-") as tmp:
+ root = Path(tmp)
+ sentinel = root / "admin-sentinel"
+ sentinel.write_text("synthetic-file-only")
+ provider = root / "provider.py"
+ provider.write_text("import os,subprocess,sys\nenv=os.environ.copy()\nenv['ANTHROPIC_API_KEY']='synthetic-provider-only'\nraise SystemExit(subprocess.call(sys.argv[sys.argv.index('--')+1:],env=env))\n")
+ ext = BwrapExtension({"base_dir": str(root / "sandboxes"), "credential_routes": {
+ "synthetic": {"profiles":["profile.scope-proof"], "projects":["scope-proof"], "actors":["agt"], "exec_argv":[sys.executable,str(provider),"--"]}}})
+ context = {"actor":"agt", "project":"scope-proof", "run_id":"scope-proof-1", "profile_id":"profile.scope-proof"}
+ # Inherited values are synthetic. Real owner credentials are never read.
+ before = {key:os.environ.get(key) for key in ("BAO_TOKEN","VAULT_TOKEN","AWS_SECRET_ACCESS_KEY","SSH_AUTH_SOCK")}
+ for key in before:
+ os.environ[key] = "synthetic-inherited-only"
+ handle = None
+ try:
+ handle = ext.provision(Profile(id="profile.scope-proof",version="1",extension="ext.bwrap"), {}, "localhost")
+ ext.wait_ready(handle)
+ sandbox = SandboxHandle(sandbox_id=handle["sandbox_id"],host="localhost",reachability={"pid":handle["pid"],"workspace_dir":handle["workspace_dir"]})
+ calls=[]
+ def execute(argv, input_text, timeout, routes=()):
+ calls.append(list(routes))
+ raw=ext.execute(handle,argv,credential_route_refs=list(routes),execution_context=context,timeout_seconds=timeout,max_output_bytes=4096,stdin_text=input_text)
+ return type("Result",(),raw)()
+ sandbox._owner_execute=execute
+ sandbox._owner_workload_execute=lambda argv,stdin,timeout: execute(argv,stdin,timeout,["synthetic"])
+ transport=transport_from_sandbox(sandbox)
+ probe = "import os,pathlib,subprocess; assert not pathlib.Path("+repr(str(sentinel))+").exists(); assert all(k not in os.environ for k in "+repr(list(before))+"); assert subprocess.check_output(['python3','-c',\"import os; print(os.environ.get('BAO_TOKEN','absent'))\"]).strip()==b'absent'; "
+ for workload in (False,True,False):
+ check = probe + ("assert os.environ['ANTHROPIC_API_KEY']=='synthetic-provider-only'; print(os.environ['ANTHROPIC_API_KEY'])" if workload else "assert 'ANTHROPIC_API_KEY' not in os.environ; print('clean')")
+ result=(transport.run_workload if workload else transport.run)(["python3","-c",check],timeout=10)
+ assert result.returncode==0, result.stderr
+ assert result.stdout == ("[REDACTED]\n" if workload else "clean\n")
+ assert calls==[[],["synthetic"],[]]
+ finally:
+ teardown=ext.teardown(handle) if handle else {}
+ for key,value in before.items():
+ if value is None: os.environ.pop(key,None)
+ else: os.environ[key]=value
+ assert teardown.get("workspace_removed")=="True"
+ print(json.dumps({"scope":"disposable bwrap via Glas transport; not interactive assignment", "model_calls":0,"real_credentials_read":False,"host_file_denied":True,"inherited_env_and_subprocess_denied":True,"credential_routes_by_command":calls,"provider_output_redacted":True,"subsequent_command_clean":True,"workspace_removed":True}))
+
+if __name__ == "__main__": main()
--- a/docs/harness-contract.md
+++ b/docs/harness-contract.md
@@ -80,9 +80,17 @@
not treated as sandbox availability.
The gateway binds local execution to the exact create-time consumer: actor,
-project, and resolved request id as `run_id`. Every owner command forwards the
-selected profile's value-free `credential_route_refs` and a timeout capped by
-its limit. The binding is process-local and excluded from serialized handles.
+project, and resolved request id as `run_id`. Housekeeping `run` commands
+(executable lookup, task creation/removal, Git inspection and artifact capture)
+request no credential routes. Only the selected rein's explicit `run_workload`
+command forwards the selected profile's value-free `credential_route_refs`.
+Both bindings cap timeouts by the profile limit and remain process-local,
+excluded from serialized handles. An absent workload binding refuses rather
+than using the housekeeping binding. SSH profiles with credential routes refuse
+because SSH has no owner-mediated credential delivery contract. These bindings
+narrow trusted gateway behavior; they do not authenticate arbitrary Python
+callers, remove task-scoped MessagesOwner routes or establish isolation of
+the caller's interactive runtime.
An unbound local descriptor refuses execution; no consumer namespace entry or
host execution fallback exists. Owner timeouts and truncated output fail closed.
Generated task specs travel over stdin to an exclusive mode-0600 writer inside
@@ -187,3 +195,10 @@
Unknown remains null, including failure before provider execution. A reported
alias does not attest an exact provider revision or conversation identifier.
See `docs/evidence/2026-10-03-emergent-session-readiness-review.md`.
+
+
+`scripts/prove-credential-command-scope.py` exercises the Glas transport against
+a disposable real bwrap namespace with synthetic material. It checks host-file
+absence, inherited credential-variable denial through a subprocess, explicit
+workload-only provider delivery, output redaction, subsequent-command absence
+and teardown. It uses no provider or model and cannot promote a runtime profile.
--- a/workplans/GLAS-WP-0012-first-local-profile-production-proof.md
+++ b/workplans/GLAS-WP-0012-first-local-profile-production-proof.md
@@ -423,3 +423,28 @@
available model/session metadata. The current lifecycle exposes no continuity
event API. Existing owner-delivery blockers and all task/readiness states remain;
local deterministic tests are not governed provider or isolation acceptance.
+
+
+## 2026-10-16 NetKingdom isolated integration preparation
+
+Prepared, without owner deployment or readiness promotion, a Glas change that
+separates credential-free housekeeping commands from explicit rein workload
+execution. Both concrete adapters use the workload path; SSH selections with
+credential routes refuse because that transport has no owner delivery contract.
+Full regression: 141 passed. Real disposable bwrap/Glas transport proof passes
+synthetic host-file denial, inherited credential environment and subprocess
+denial, workload-only delivery, redaction, subsequent-command absence and
+teardown. No provider/model call or real credential read occurred.
+
+Latest owner dependency sources supersede the stale missing-lane account:
+September 27 native lanes were activated and revoked; corrected immutable
+owner runtime is `818b1b7c…` (October 15 startup proof), not yet installed or
+admitted on Railiance. REINAH-WP-0008-T07 retains memo lifecycle acceptance,
+installation, rehearsal, renewal/pin updates, native approvals and bounded
+successful model/tool/commit acceptance. Any subsequent build containing this
+patch has a different source/artifact pin requiring owner admission.
+
+This is a reviewable patch in Custodian's NetKingdom change bundle; no canonical
+source synchronization or workplan task completion is implied. CUST-WP-0073
+continues to require admission of the actual interactive assignment, including
+its existing host credential and external tool paths, not a disposable fixture.

View file

@ -0,0 +1,5 @@
{
"exit_code": 0,
"stdout": "",
"stderr": ""
}

View file

@ -0,0 +1,120 @@
{
"owner": "glas-harness",
"canonical_source_modified": false,
"isolated_tree": "/tmp/netkingdom-agent-isolation-20261016/glas-harness",
"sources": [
{
"repo": "glas-harness",
"head": "dc88f302044c7c2b41795958527e64be8a83e3ab",
"status": "M .custodian-brief.md\n M WORK-RECORDS.md\n"
},
{
"repo": "sand-boxer",
"head": "53f800c4f7a9c91469834d04ef6f58e906b0bd49",
"status": ""
},
{
"repo": "rein-aharness",
"head": "be5ef400861a5e31a31f29d173990c7a143fb189",
"status": ""
}
],
"changes": [
{
"path": "src/glas_harness/contract.py",
"baseline_sha256": "ad5f63b4a22ff65a7e9bf956ea65b04d55fe3d7268bbbdf6956aabd118ce4238",
"candidate_sha256": "db9a3540221229de9e4a6ec04216f7bea9e99136f26931418a994c37b6eb21df"
},
{
"path": "src/glas_harness/gateway.py",
"baseline_sha256": "d6c7636b7d1fb1d16fa66f7105ff18a769414eb4c99f21e62557c8b04c3fe9a8",
"candidate_sha256": "5e998bfa53ade5dafbae799dc04b77031b6414e2af49797f45727d59d7397d42"
},
{
"path": "src/glas_harness/transport.py",
"baseline_sha256": "91f5a5adeb7a27d0a828eb0c801fd2381f7d272a521cd5f563d04d5fa022d0f2",
"candidate_sha256": "fa1686298b7403390396fa2786a2b6711609980a4a0fca5f2e38f250ae640b5c"
},
{
"path": "src/glas_harness/reins/rein_aharness.py",
"baseline_sha256": "67bf8369501c96227cc5f89158ad4c41cf2c86bd7f4235f162e7da8cadcc8f05",
"candidate_sha256": "2f725a4dbda311bf2626959dd439ab9d70e82021496fecf61d9319091873c7a7"
},
{
"path": "src/glas_harness/reins/rein_openweights.py",
"baseline_sha256": "7da551d0bfc42588897ecae6145bdd90813dd64611ff818a03ea5144ebd8dd90",
"candidate_sha256": "e0f7261cafed7f4fe67d34bf27cf431dfeca18536c1cbd84626fa25017cd44ad"
},
{
"path": "tests/test_gateway.py",
"baseline_sha256": "0197543fda862a1c6cb1e2c974ef4ea7969017fe8ca3f212e5c0d7e8d13308de",
"candidate_sha256": "8ecae8010b1c6182591b12b335af8f2f6e6e08366b646eb138a4ef08679b6634"
},
{
"path": "tests/test_transport.py",
"baseline_sha256": "27b3d0e2d78e128e2265467835d92d7ab9dcc06637e4ffc236bdc791488703c9",
"candidate_sha256": "50c86170d9dc9cecbef49886a733f6ca78b5a8be5d67701b521d98bd81dfaabe"
},
{
"path": "tests/test_rein_aharness.py",
"baseline_sha256": "3d34a6dfdb8962263d254e5f40f64147af7da15f6d1ac377854ff688cd7a9032",
"candidate_sha256": "5dc802830f902d4e4a502c981e7626a8282b6dbd4e9829659f9efedfcf1dd16e"
},
{
"path": "tests/test_rein_openweights.py",
"baseline_sha256": "1b0c4d16e0c885f6dd0f25dac3de3372a93ab3d65c1432b0eebac045625b4665",
"candidate_sha256": "c71c66976982e5375dd2513e2f392e8884305be1690856a37fa5a78075aee222"
},
{
"path": "tests/test_rein_session_isolation.py",
"baseline_sha256": "0c6a875cd8529b3f084a3b055a1edd86af0703489ced4669671dff817c296a84",
"candidate_sha256": "699b554f5889df5afee2b556e50602876f849ef7fde1dd612408a7acfc597dc1"
},
{
"path": "scripts/prove-credential-command-scope.py",
"baseline_sha256": null,
"candidate_sha256": "acc7ca6e29b3ace36c734ac3478f48ba901805e9a9acca98bd1ee8820f6fa1a8"
},
{
"path": "docs/harness-contract.md",
"baseline_sha256": "96e274ea547844e5062eab96c05231bc4d9ffb81306f1e9c5e3cc1ee2c8c87f9",
"candidate_sha256": "0bc3a43ff9a1b72c4668d6ca8e936163f865c2b302c920f7ede6c5e00d59a39d"
},
{
"path": "workplans/GLAS-WP-0012-first-local-profile-production-proof.md",
"baseline_sha256": "83978dc6cfdc836cca7b5cd12b03b878c944d67598f9505a196701fa534f6cfc",
"candidate_sha256": "881ab0f5ba3bb43f5404c8f4cd23f9628e014992ba88fc13f541f0fa8b7b1eaa"
}
],
"patch_sha256": "83eeeb0017603aabae0ff49a23f96248f677f6c9f3e2c01b22f6d0416fca69c7",
"dependency_sources": [
{
"path": "/home/worsch/sand-boxer/src/sandboxer/extensions/bwrap.py",
"sha256": "eff580a498f3609d3e07e41440f926016fd46a7b0c6273c37445921ea6e03cb0"
},
{
"path": "/home/worsch/sand-boxer/src/sandboxer/extensions/bwrap_runner.py",
"sha256": "c83cdd2758bae58cd5d5694f5d6752736f59d479cfc6e9f0f8841c1f5596cba6"
},
{
"path": "/home/worsch/sand-boxer/workplans/SAND-WP-0015-bwrap-runtime-and-private-state.md",
"sha256": "230d1ef37aa9c2023335a617492a72678c4671a8bc82d5577e9d7a7cea6e8fe4"
},
{
"path": "/home/worsch/rein-aharness/rein_aharness/adapter.py",
"sha256": "de55aec9a19c5e17c59febb7e0481400ab4a47880f54bf8ca46b6dd8ec8fcf17"
},
{
"path": "/home/worsch/rein-aharness/rein_aharness/messages_owner.py",
"sha256": "14129bc0ae9611d5b2e04e277a292b2ee09b32f18d896b94741038fdab867abd"
},
{
"path": "/home/worsch/rein-aharness/workplans/REINAH-WP-0008-simpler-metered-retry.md",
"sha256": "3f46cf1f278e35be994772cb2d7e6d95f570fb5bfba28c6b55dc89b663d25f89"
},
{
"path": "/home/worsch/the-custodian/.kaizen/agents/custodian-codex/supervision.json",
"sha256": "407340493ffe584e9a245911d01f60e8f9ec1478f84478388f0210fd0c8b1a6d"
}
]
}

View file

@ -0,0 +1,7 @@
{
"command": "PYTHONPATH=/tmp/netkingdom-agent-isolation-20261016/glas-harness/src:/tmp/netkingdom-agent-isolation-20261016/sand-boxer/src /home/worsch/glas-harness/.venv/bin/python -m pytest /tmp/netkingdom-agent-isolation-20261016/glas-harness/tests -q",
"exit_code": 0,
"stdout": "141 passed in 10.89s",
"python": "/home/worsch/glas-harness/.venv/bin/python",
"native_provider_requests": 0
}

View file

@ -0,0 +1,44 @@
# Approval exact-binding confirmation repair
Approval owner source preparation from clean source commit
`477c683991fda3c01e2af98a18f5a8719ee9dbc9`, in an isolated temporary checkout.
Pending canonical WP0004 closure changes, generated UUIDs and unrelated dirt
remain untouched. `owner-dirty-baseline.patch` preserves that observed state;
`implementation.patch` applies cleanly on top of it.
Reproduction on unchanged production client source: canonical binding dict
equality accepts nested True/1, False/0, 1/1.0 and 1/True substitutions. Missing,
wrong and boolean served native digests also went unchecked. Seven regression
cases failed their expected refusal, while a valid nested/key-order case passed.
This is client confirmation ambiguity, not proof of a production exploit or
native acceptance failure.
The minimal fix reuses Approval's existing native `binding_digest`: recompute
the served five-field act digest, compare it with the expected act digest, and
require the served digest field to match. No new digest, API schema, authority,
service or approval contract is introduced. Native binding, approval-free PDP
and full consumed request digests retain their separate meanings.
Twelve added cases cover four Python-equal/JSON-distinct substitutions with
stale and recomputed served digests, three missing/invalid digest cases, and valid
nested types plus reordered keys. The final confirmation suite passes 36 tests.
Final focused command including consume provenance and the unavailable-server
case passes 44 tests. A broader earlier run passed 101 and failed one existing
200ms transport test because isolated child startup reached the total deadline
instead of returning its expected `unreachable` text; both outcomes fail closed.
Its focused retry passed. That transient failure is retained in validation.json.
New bounded low-risk source task: APPROVAL-WP-ADHOC-2026-10-16-T01. WP0004 closure
is not reopened, and existing WP0002 native residuals remain open. This source
preparation is not formal delegated-owner assent, signed approval or native
acceptance. No live credential, approval service, OpenBao or protected operation
was used. Coordinator review/integration/publication/sync remain pending.
After integration, Platform must pin the actual integrated confirmation client
source. Prepared `approval_engine/execution_confirmation.py` SHA256 is
`afd4383d6785b12be9650d1cb3ef84ccbb1b57cd271d38d55e75875c46e85a79`.
Its actual mediator must retain independently authenticated provider transport,
exact fresh claim/signed decision/body/operation checks and the same live one-shot
journal admission. This historical confirmation fact never grants execution or
retries uncertain protected work. Native validation must use the final pinned
client, and prior disposable proof must state which earlier client it exercised.

View file

@ -0,0 +1,140 @@
diff --git a/approval_engine/execution_confirmation.py b/approval_engine/execution_confirmation.py
index 2fef8b9..fa7daaa 100644
--- a/approval_engine/execution_confirmation.py
+++ b/approval_engine/execution_confirmation.py
@@ -8,7 +8,7 @@ from datetime import datetime
from typing import Any
from urllib.parse import quote
-from .binding import DIGEST_RE, canonical_binding
+from .binding import DIGEST_RE, binding_digest
from .pep import ApprovalHTTPClient, ApprovalProtocolError, _ID_RE
@@ -71,7 +71,7 @@ class ExecutionConfirmationClient(ApprovalHTTPClient):
if not isinstance(expected_pdp_digest, str) or not DIGEST_RE.fullmatch(expected_pdp_digest):
raise ApprovalProtocolError("exact approval-free PDP digest is required")
try:
- expected = canonical_binding(expected_binding)
+ expected = binding_digest(expected_binding)
except (TypeError, ValueError, KeyError):
raise ApprovalProtocolError("expected act binding is invalid") from None
obj = self._request("GET", f"/v1/approvals/{quote(approval_id, safe='')}")
@@ -81,7 +81,11 @@ class ExecutionConfirmationClient(ApprovalHTTPClient):
raise ApprovalProtocolError("consumption object is not a decision")
served = obj.get("binding")
try:
- same_act = isinstance(served, dict) and canonical_binding(served) == expected
+ same_act = (
+ isinstance(served, dict)
+ and binding_digest(served) == expected
+ and served.get("digest") == expected
+ )
except (TypeError, ValueError, KeyError):
same_act = False
if not same_act or served.get("pdp_digest") != expected_pdp_digest:
diff --git a/tests/test_execution_confirmation.py b/tests/test_execution_confirmation.py
index fed3f83..9892ff3 100644
--- a/tests/test_execution_confirmation.py
+++ b/tests/test_execution_confirmation.py
@@ -127,3 +127,50 @@ def test_denied_read_never_represents_confirmation(engine, app, tmp_path):
raise HTTPError(req.full_url, status, "refused", {}, None)
with pytest.raises(ApprovalProtocolError, match="unauthorized"):
confirmer(client(tmp_path, opener), obj)
+
+
+@pytest.mark.parametrize("original,substitute", [(True, 1), (False, 0), (1, 1.0), (1, True)])
+@pytest.mark.parametrize("recompute_served_digest", [False, True])
+def test_confirmation_refuses_python_equal_json_distinct_target(
+ engine, tmp_path, original, substitute, recompute_served_digest
+):
+ expected = binding(target={"nested": [{"value": original}]})
+ obj = engine.create(expected, validity(), pdp_digest=FREE, pdp_path=True,
+ human_control=True)
+ engine.add_entry(obj.id, "human:founder", principal_type="human")
+ engine.consume(obj.id, FULL, decision_id="decision:original")
+ result = engine.get(obj.id).as_dict()
+ result["binding"]["target"] = {"nested": [{"value": substitute}]}
+ if recompute_served_digest:
+ from approval_engine.binding import binding_digest
+ result["binding"]["digest"] = binding_digest(result["binding"])
+ assert result["binding"]["target"] == expected["target"]
+ with pytest.raises(ApprovalProtocolError, match="binding does not match"):
+ client(tmp_path, lambda *_a, **_k: Response(result)).confirm_consumption(
+ obj.id, FULL, "decision:original", expected_binding=expected,
+ expected_pdp_digest=FREE)
+
+
+@pytest.mark.parametrize("digest", [None, "sha256:" + "00" * 32, True])
+def test_confirmation_requires_served_native_digest_correspondence(engine, tmp_path, digest):
+ obj = consumed(engine)
+ result = engine.get(obj.id).as_dict()
+ if digest is None:
+ result["binding"].pop("digest")
+ else:
+ result["binding"]["digest"] = digest
+ with pytest.raises(ApprovalProtocolError, match="binding does not match"):
+ confirmer(client(tmp_path, lambda *_a, **_k: Response(result)), obj)
+
+
+def test_confirmation_accepts_nested_json_types_and_key_order(engine, tmp_path):
+ expected = binding(target={"b": [True, False, 1, 1.0], "a": {"unicode": "ä"}})
+ obj = engine.create(expected, validity(), pdp_digest=FREE, pdp_path=True,
+ human_control=True)
+ engine.add_entry(obj.id, "human:founder", principal_type="human")
+ engine.consume(obj.id, FULL, decision_id="decision:original")
+ result = engine.get(obj.id).as_dict()
+ result["binding"]["target"] = dict(reversed(list(expected["target"].items())))
+ assert client(tmp_path, lambda *_a, **_k: Response(result)).confirm_consumption(
+ obj.id, FULL, "decision:original", expected_binding=expected,
+ expected_pdp_digest=FREE)["approval_id"] == obj.id
diff --git a/workplans/ADHOC-2026-10-16.md b/workplans/ADHOC-2026-10-16.md
new file mode 100644
index 0000000..cd19170
--- /dev/null
+++ b/workplans/ADHOC-2026-10-16.md
@@ -0,0 +1,44 @@
+---
+id: APPROVAL-WP-ADHOC-2026-10-16
+type: workplan
+title: "Repair exact consume-confirmation native binding comparison"
+domain: infotech
+repo: approval-engine
+status: finished
+flavor: implementation
+owner: codex
+topic_slug: netkingdom
+created: "2026-10-16"
+updated: "2026-10-16"
+---
+
+## Refuse Python-equal JSON-distinct consumed act bindings
+
+```task
+id: APPROVAL-WP-ADHOC-2026-10-16-T01
+status: done
+priority: high
+```
+
+Bounded source repair demanded by the CUST-WP-0080 strict execution-seam proof.
+INTENT basis: exact binding and authenticated consumption evidence; no authority
+or native grant is added. Existing canonical native-five-field digest is reused.
+ExecutionConfirmationClient now recomputes the served and expected digests and
+requires the served digest field to correspond, replacing Python dict equality
+which accepted nested True/1, False/0 and integer/float substitutions.
+
+Before repair seven regression cases wrongly confirmed (four target type
+substitutions and three absent/wrong/type-invalid served digest fields); valid
+nested types with reordered keys passed. The repair retains this failure history.
+Twelve added regression cases cover exact native JSON correspondence, including
+substitutions with both retained and recomputed served digests, without
+changing the native digest algorithm, request/PDP digest contract or API schema.
+Canonical integration/publication and the Platform mediator's final provider
+client source pin remain with the coordinator; preparation does not claim them.
+
+Existing APPROVAL-WP-0004 closure and generated identifiers are untouched.
+APPROVAL-WP-0002-T01/T04/T05 remain existing live native acceptance obligations;
+none is promoted or completed here. No production auth, approval mutation,
+credential, deployment or backend operation was used. This completed low-risk
+local source repair introduces no residual native obligation beyond those
+existing records and the coordinator's integration of this exact artifact.

View file

@ -0,0 +1,43 @@
diff --git a/.custodian-brief.md b/.custodian-brief.md
index 4e8f8d3..ee8ca96 100644
--- a/.custodian-brief.md
+++ b/.custodian-brief.md
@@ -2,7 +2,7 @@
# Custodian Brief — approval-engine
**Domain:** infotech
-**Last synced:** 2026-10-11 13:46 UTC
+**Last synced:** 2026-10-16 06:27 UTC
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
## Active Workstreams
@@ -20,7 +20,7 @@ Progress: 3/6 done | workplan_id: `4fa25ad5-f5d0-5592-aa59-085f8ee3edaf`
## Inbox Hygiene
-**Stale unread:** 10 message(s) older than 3 day(s) — triage at session start.
+**Stale unread:** 11 message(s) older than 3 day(s) — triage at session start.
**Missing thread_id:** 9 unread message(s) lack supersession chains.
- ! informed-decision: INFD-WP-0005: service-requested approvals from informed-decision intake (two small asks) `59c5ee82`
- ! flex-auth: FLEX-WP-0020 handoff request (consumer) `2523510b`
diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md
index 2110857..f7cd8df 100644
--- a/WORK-RECORDS.md
+++ b/WORK-RECORDS.md
@@ -13,6 +13,7 @@
| workplan | APPROVAL-WP-0001 | finished | — | workplans/APPROVAL-WP-0001-v07-alignment-and-engine-spine.md |
| workplan | APPROVAL-WP-0002 | blocked | — | workplans/APPROVAL-WP-0002-production-readiness-and-consumer-adoption.md |
| workplan | APPROVAL-WP-0003 | finished | — | workplans/APPROVAL-WP-0003-reissue-expired-approvals.md |
+| workplan | APPROVAL-WP-0004 | finished | — | workplans/APPROVAL-WP-0004-exact-consume-source-provenance.md |
| task | APPROVAL-WP-ADHOC-2026-10-10-T01 | done | — | workplans/ADHOC-2026-10-10.md |
| task | APPROVAL-WP-ADHOC-2026-10-11-T01 | done | — | workplans/ADHOC-2026-10-11.md |
| task | APPROVAL-WP-ADHOC-2026-10-11-T02 | done | — | workplans/ADHOC-2026-10-11.md |
@@ -32,6 +33,8 @@
| task | APPROVAL-WP-0002-T05 | wait | — | workplans/APPROVAL-WP-0002-production-readiness-and-consumer-adoption.md |
| task | APPROVAL-WP-0002-T06 | done | — | workplans/APPROVAL-WP-0002-production-readiness-and-consumer-adoption.md |
| task | APPROVAL-WP-0003-T01 | done | — | workplans/APPROVAL-WP-0003-reissue-expired-approvals.md |
+| task | APPROVAL-WP-0004-T01 | done | — | workplans/APPROVAL-WP-0004-exact-consume-source-provenance.md |
+| task | APPROVAL-WP-0004-T02 | done | — | workplans/APPROVAL-WP-0004-exact-consume-source-provenance.md |
| intake | APPROVAL-IN-0001 | open | blue | intakes/intakes.md |
| intake | APPROVAL-IN-0002 | closed | blue | intakes/intakes.md |
| intake | APPROVAL-IN-0003 | closed | — | intakes/intakes.md |

View file

@ -0,0 +1,5 @@
{
"exit_code": 0,
"stderr": "",
"pending_WP0004_closure_and_UUIDs_preserved": true
}

View file

@ -0,0 +1,14 @@
{
"workplan_id": "4fa25ad5-f5d0-5592-aa59-085f8ee3edaf",
"id": "03ffe09e-b794-43c8-8010-9a55425a4351",
"topic_id": null,
"task_id": null,
"decision_id": null,
"event_type": "note",
"summary": "Approval owner bounded exact-confirmation source repair: reproduced Python-equal JSON-distinct target acceptance and unchecked served native digest, then reused native binding_digest recomputation and exact field correspondence.12 new cases;36confirmation tests and44focused tests passed. Intermediate200ms transport timing failure retained, focused retry passed. Patch/manifest under approval-confirmation; pending canonical integration/final Platform pin. Existing WP0004 closure/UUIDs and native WP0002 obligations unchanged; no live auth/effect.",
"detail": null,
"author": "codex",
"session_id": null,
"created_at": "2026-10-16T06:29:09.227024Z",
"workstream_id": "4fa25ad5-f5d0-5592-aa59-085f8ee3edaf"
}

View file

@ -0,0 +1,135 @@
# Thin Access Approval fact reader — owner source contract proposal
Owner scope: Approval Engine / PIP. Work: APPROVAL-WP-0005-T01, selected source
subset of APPROVAL-WP-0002-T01/T05 under CUST-WP-0080. This interprets the existing
claim schema 0.1, not a new API/schema/signature or policy grant. Access's B2
implementation stays DENY until its separately reviewed complete successor.
## Authoritative source and guarantee
Only server-installed, independently admitted provider origin and transport may
GET `/v1/approvals/{id}/claim`, with least-scope `approval:read` credential and
exact admitted store tenant. No caller URL/opener/key/verified flag, redirects,
environment proxy, caller JSON or public same-channel key bootstrap can supply
this provenance. Owner transport must enforce total deadline/size, exact 200
application/json UTF-8, no encoding, duplicate-key/nonfinite/malformed JSON
refusal, no retry and bounded errors without bearer/body leakage. Provider
unavailability refuses this source join. Never invoke a credential-carrying
Python subprocess as the Go adapter; reuse Go's existing transport boundary.
At the provider observation, `valid_now: true` AND `binding.human_control: true`
means the configured required count of distinct entries is met and every entry
has verified `principal_type=human`. `/entries` obtains identities/types only from
its authenticator, rejects non-human binds for this declaration, and persists
UNIQUE(approval_id, subject_id); `_evaluate` repeats the threshold/human check.
It does NOT mean required_count is two, requester/actor/principal is human,
directory-derived tenant membership, a particular MFA/assurance level, policy
eligibility, uncompromised source, native issuer admission, or continuing
validity after the observation. Consumer trusts this owner evaluation instead
of fetching identities/counting approvers or revalidating human JWTs. Native
issuer/profile acceptance is still T01, not established by synthetic vectors.
## Minimal typed fact validation
The submitted claim and fetched observation must each satisfy existing schema
0.1 with exact JSON types; `human_control` must be present and exactly true on
this lane despite being historically optional in the generic schema. Require
schema_version=0.1, kind=approval-claim, issuer=approval-engine, exact expected
approval UUID, state=valid, valid_now=true, consumed=false, reason_code=ok,
pdp_path=true and non-null lowercase sha256 pdp_digest. Reject decision-shaped
keys and unknown schema members (except optional informational yields_to).
The signed/requesting service must never become a human approver by inference.
At one captured UTC validation instant now, require zoned RFC3339 timestamps,
positive integral ttl_seconds, observed_at<=now<not_after and
not_after=observed_at+ttl_seconds. Require not_before<=now<expires_at. Do not
invent skew or extend TTL; a separately admitted clock policy is needed to
relax the zero-skew default. The provider default TTL is 30 seconds but source
configuration may differ; an Access-owned maximum may only shorten it.
Compare exact five-field act against the owner-derived normalized proposed act,
including all nested target values; no action vocabulary translation is owned
here. Recompute native binding.digest from those five fields and require exact
served and expected digest correspondence. Match pdp_digest to Access's actual
ApprovalBindingDigest over the exact normalized original request (excludes only
top-level context.approval). Preserve execution_contract and all other context.
Never substitute full request_digest, native act digest or a guessed Go digest.
The PDP digest proves correspondence, not decision authenticity or approval
source authenticity. Registry/normalization changes must fail or reissue.
## Original request is immutable; fresh observation stays out-of-band
The original submitted context.approval must remain byte/value-equivalent under
Access's existing canonical request rules. Do not replace it, update freshness,
change binding/declarations, or manufacture an evaluated refreshed request.
Validate its own original freshness/validity too; a newly fetched observation
cannot rescue a stale original claim. Require all non-freshness authority facts
to match between the submitted and fetched claims: schema/kind/issuer/id,
state/valid_now/consumed/reason_code, binding and validity. Optional yields_to
is informational only. Each native binding is independently recomputed.
Freshness is validated separately on both observations; a later observation
may have a later freshness window without changing the signed request.
Return a package-private/server-created typed observation handle only after
these checks. Access may bind its source identity/revision, observed_at,
not_after, fetched-claim content digest and validation time into owner-produced
signed provenance separately from unchanged request_digest and
approval_binding_digest. This does not require changing the Approval schema;
Access owns the minimal existing provenance representation and signer contract.
An HTTP caller cannot instantiate this handle or set its verified state.
Suggested Go boundary, for Access to implement in its existing process:
`ApprovalFactSource.Observe(ctx, approvalID) (Observation, error)` reads only
provider bytes plus source provenance; a separate package-private validator
joins Observation with the immutable normalized request, submitted claim and
captured validation time. The handle retains detached raw provider bytes and
strict parsed numbers (json.Number), not caller-installable validation flags.
Neither this reader nor its validator evaluates policy. Access's existing
single policy evaluator consumes the verified factual handle without rewriting
the request. Callers may not supply a ready-made Observation on the HTTP body.
Effective input deadline is the minimum of ORIGINAL submitted freshness,
fetched freshness, approval expiry, authenticated caller expiry and operation/
decision deadlines. No equality at an expiry boundary is accepted. Refetching
does not renew the original full request. Revocation/use may race a read; the
PEP still performs one original exact consume CAS before effect and retains
the same live Platform journal admission, deadlines and unknown-outcome rules.
Access never consumes or executes. Historical confirm_consumption cannot
substitute for this fresh predecision source validation.
## Go canonicalization and golden vectors
`examples/access-claim-reader-vectors.json` contains producer-generated native
canonical UTF-8 bytes/digests and source lifecycle observations, plus explicitly
mutated refusal fixtures. Python dict equality and Go decoding numbers into
float64 lose authority distinctions: True/1, 1/1.0 and integers above 2^53 differ.
Go default json.Marshal additionally escapes HTML/U+2028 differently. Retain
number tokens with UseNumber and implement/test compatibility with Approval's
existing Python json.dumps(sort_keys=True,separators=(',', ':'),ensure_ascii=False)
format; do not silently normalize types or hash whole binding/freshness.
UseNumber preserves number tokens but is NOT a canonicalizer: producer parsing
of `1e-7` emits `1e-07`, `1e20` emits `1e+20`, `1.0` remains distinct from `1`,
and negative floating zero emits `-0.0`. A signed typed Go envelope alone does
not preserve or authenticate Python's original numeric representation.
These finite vectors are a minimum, not proof of a complete Python float/string
port. A thin pilot may fail closed on unsupported numeric/string domains only
if its actual owner-compiled operation contract excludes those values and Access
declares/tests that boundary. It may not silently change the global Approval
algorithm or accept a digest without checking the proposed act. Required vectors
cover bool/int/float distinction, large integer, Unicode/HTML/U+2028, reordered
keys, nested containers, exponent formatting and negative floating zero. These
are authoritative producer vectors for the domains shown, not arbitrary new
restrictions on current pilot metadata. No currently authoritative narrow numeric
restriction was established by this review, so it cannot be presumed. If a
small shared producer-owned Go canonicalization helper becomes necessary, scope
it explicitly to the actual consumer need and test against these producer bytes;
do not invent a second unverified serialization algorithm in the adapter. This
review provides vectors only, not that runtime implementation. The Go owner must
return exact accepted/refused vector results and transport negatives
(redirect/proxy/duplicate/size/deadline).
The superseded service-http-join-proposal-r1 B3 refreshed-evaluation wording is
changes-requested for this immutable-context path. B2's source reader can proceed
against this proposal after Access's own design/conformance review. No foreign
owner assent, policy activation, live credential or native acceptance is implied.

View file

@ -0,0 +1,15 @@
{
"reviewer": "approval-engine-owner (agent approval-engine, codex)",
"decision": "changes_requested",
"comment": "INTENT Purpose and exact binding/claim boundary: B2 can reuse existing GET claim schema0.1 and verified human-control predicate without republishing approver identities. Superseded B3 refreshed evaluated-request/context design cannot satisfy the exact original strict handoff; retain original context/full and approval-free digests and verify fresh provider observation out-of-band. Work APPROVAL-WP-0005-T01; source base eece796b8bbee19551f6aa07ad389cbf83cabcdb. No policy activation, issuer admission, foreign owner assent or native acceptance.",
"reviewed_artifact": "/home/worsch/the-custodian/docs/changes/netkingdom-target-2026-10-16/access-native-source/service-http-join-proposal-r1.json",
"reviewed_sha256": "e0f8f12c48faf2331cf366591028577beffe617250d7005dcaf2a8b7396535fc",
"owner_contract": "docs/access-claim-fact-reader.md",
"owner_contract_sha256": "3dfb7987a4d9fe461b917cfa5bae7beef61bc4d9a4561fdded3e90128f5966de",
"required_returns": [
"Access own B2 contract/conformance review and exact native canonicalization parity; original submitted context/digests retained",
"Owner-admitted read identity/store tenant and trusted provider transport separate from source fixture tests",
"Actual runtime source integration and original consumer/journal/cas path before any policy eligibility successor"
],
"native_accepted": false
}

View file

@ -0,0 +1,14 @@
{
"workplan_id": "4fa25ad5-f5d0-5592-aa59-085f8ee3edaf",
"id": "c60f783b-47af-4d98-9495-686b59bc6619",
"topic_id": null,
"task_id": null,
"decision_id": null,
"event_type": "note",
"summary": "Approval owner reviewed authoritative Access B2 claim contract under scoped WP0002 T01/T05 demand, prepared WP0005 source review and producer vectors. Original submitted context and freshness remain intact; fresh source checked out-of-band. Distinct verified human guarantee and native issuer limits documented. 44 source tests passed; 24 claim cases, 14 native Python canonical vectors and 7 transport refusal vectors delivered; Go conformance and canonical integration pending. No live auth, policy activation or native acceptance. Artifacts approval-fact-contract.",
"detail": null,
"author": "codex",
"session_id": null,
"created_at": "2026-10-16T07:44:18.335488Z",
"workstream_id": "4fa25ad5-f5d0-5592-aa59-085f8ee3edaf"
}

View file

@ -0,0 +1,13 @@
{
"command": "python3 -m pytest -q tests/test_access_claim_vectors.py tests/test_human_control.py tests/test_claim_contract.py tests/test_tenant_provenance.py",
"passed": 44,
"claim_cases": 24,
"native_canonical_vectors": 14,
"transport_refusal_vectors": 7,
"native_canonical_vector_test": "actual existing producer bytes/digests verified",
"claim_vector_test": "positive differential observations reproduced against actual Engine; signed human-control/provenance regressions passed",
"consumer_go_conformance": "pending Access implementation; negative fixture expectations are contract, not executed Go acceptance",
"patch_check_exit": 0,
"canonical_source_mutated": false,
"native_accepted": false
}

View file

@ -0,0 +1,52 @@
# Approval-owned Go fact data adapter
Source proposal under APPROVAL-WP-0005-T03. Base owner revision:
`eece796b8bbee19551f6aa07ad389cbf83cabcdb`. Worktree:
`/tmp/netkingdom-approval-go-fact-20261016`. Canonical source/dirt is untouched.
Access agreed the exact module/API before implementation:
`github.com/netkingdom/approval-engine/adapters/go/approvalfact` exports
CanonicalBinding(raw JSON), ValidateClaim(raw JSON, Expected, now), and
MatchObserved(original, fetched). Fact exposes detached bytes, observation and
deadline/native digest only; it is validated data, never authenticated origin.
No credential transport, subprocess runtime, evaluator, consume or service was
added. Existing Access Go1.26.7 is used.
The Python owner primitive remains authoritative. The Go adapter reproduces
its native five-field JSON bytes, including bool/int/float identity, finite
float exponent thresholds/padding, negative floating zero, arbitrary integer
magnitudes, sorted Unicode keys, HTML and U+2028/U+2029 without Go escaping.
Strict parsing rejects duplicates, invalid Unicode/surrogates and nonfinite
values. Explicit 1MiB/128-depth/nanosecond-time bounds fail closed; no numeric
domain restriction was invented to simplify conformance.
Validation: 14 native vectors and 24 claim cases pass; Go race and vet pass.
The actual Python source differential corpus matches 14,114 exact canonical
byte/digest results, including random finite IEEE patterns, float boundaries,
subnormals, extrema, integer and Unicode cases. Existing Python human-control,
claim and provenance checks: 44 passed. This is tested source correspondence,
not exhaustive formal proof, authenticated origin or native acceptance.
Initial toolchain-selection/cache failures are retained in validation.json.
Two patch forms are provided because the initial fact-contract package was
still pending integration when this source was prepared:
- `implementation.patch` contains the pending fact-contract package plus this
Go adapter, and applies directly to the current canonical owner revision.
- `incremental-after-fact-contract.patch` contains only this next source slice;
apply after approval-fact-contract/implementation.patch. Do not apply both.
Both apply-checks pass; exact hashes and every source file hash are in
manifest.json. The local pending-contract commit is only a temporary preparation
anchor, not a published owner commit. Workplan T02 remains open for coordinator
review/integration/handoff, and native WP0002 T01/T04/T05 gates remain unchanged.
Access owns source transport authentication and the wrapper inaccessible to HTTP
callers. Expected native raw act must come from authoritative owner/compiler and
actual normalization. Access's existing float64-decoded maps cannot supply it.
The owner identified a current pilot route preserving raw request.resource only
when it proves no active target registry enrichment and applies exact existing
tenant normalization. Future overrides need authoritative raw enrichment source;
unsupported correspondence refuses. Helper success must not activate policy or
substitute a supplied digest for recomputation. Independently review and pin the
final module sources before Access reader/engine integration and native proof.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,7 @@
{
"chunk_id": "1fd0b5",
"wall_time_seconds": 0.000015916,
"exit_code": 0,
"original_token_count": 858,
"output": "WARN: git commit failed for writeback: Generated-only commits rejected: staged\n{\n \"repo_slug\": \"approval-engine\",\n \"repo_path\": \"/home/worsch/approval-engine\",\n \"source_revision\": null,\n \"source_revision_reason\": \"dirty_workplans\",\n \"issues\": [\n {\n \"severity\": \"WARN\",\n \"check_id\": \"C-33\",\n \"message\": \"WORK-RECORDS.md is missing or stale \\u2014 regenerate via fix-consistency (CUST-WP-0061-T04 generated work-record index)\",\n \"file_path\": \"WORK-RECORDS.md\",\n \"db_id\": \"\",\n \"file_value\": \"\",\n \"db_value\": \"\",\n \"fixable\": true\n },\n {\n \"severity\": \"WARN\",\n \"check_id\": \"C-11\",\n \"message\": \"Task 'APPROVAL-WP-ADHOC-2026-10-11-T02' has no state_hub_task_id\",\n \"file_path\": \"workplans/ADHOC-2026-10-11.md#APPROVAL-WP-ADHOC-2026-10-11-T02\",\n \"db_id\": \"\",\n \"file_value\": \"\",\n \"db_value\": \"\",\n \"fixable\": true\n },\n {\n \"severity\": \"WARN\",\n \"check_id\": \"C-06\",\n \"message\": \"Workplan has no state_hub_workstream_id \\u2014 not indexed in DB\",\n \"file_path\": \"workplans/APPROVAL-WP-0005-access-claim-fact-contract.md\",\n \"db_id\": \"\",\n \"file_value\": \"Approval fact contract and reusable Go data adapter\",\n \"db_value\": \"\",\n \"fixable\": true\n },\n {\n \"severity\": \"WARN\",\n \"check_id\": \"C-28\",\n \"message\": \"11 unread inbox message(s) older than 3 day(s): key-cape:ffe5aff4, informed-decision:59c5ee82, the-custodian:23172cb2, access-engine:9b8795d2, the-custodian:51e9eace, ...\",\n \"file_path\": \"\",\n \"db_id\": \"\",\n \"file_value\": \"\",\n \"db_value\": \"\",\n \"fixable\": false\n },\n {\n \"severity\": \"WARN\",\n \"check_id\": \"C-28\",\n \"message\": \"9 unread message(s) lack thread_id for supersession tracking: key-cape:ffe5aff4, informed-decision:59c5ee82, the-custodian:23172cb2, access-engine:9b8795d2, the-custodian:51e9eace\",\n \"file_path\": \"\",\n \"db_id\": \"\",\n \"file_value\": \"\",\n \"db_value\": \"\",\n \"fixable\": false\n },\n {\n \"severity\": \"WARN\",\n \"check_id\": \"C-29\",\n \"message\": \"Unread work request from informed-decision (59c5ee82) may need a workplan file: INFD-WP-0005: service-requested approvals from informed-decision intake (two small asks)\",\n \"file_path\": \"\",\n \"db_id\": \"\",\n \"file_value\": \"\",\n \"db_value\": \"\",\n \"fixable\": false\n },\n {\n \"severity\": \"WARN\",\n \"check_id\": \"C-29\",\n \"message\": \"Unread work request from flex-auth (2523510b) may need a workplan file: FLEX-WP-0020 handoff request (consumer)\",\n \"file_path\": \"\",\n \"db_id\": \"\",\n \"file_value\": \"\",\n \"db_value\": \"\",\n \"fixable\": false\n }\n ],\n \"fixes_applied\": [\n \"bindings: synced 7/7\",\n \"C-17 cleared: pushed 1 backlogged commit(s)\",\n \"C-33 fixed: regenerated WORK-RECORDS.md\",\n \"C-11 skipped: task 'APPROVAL-WP-ADHOC-2026-10-11-T02' in finished workstream \\u2014 not created\",\n \"C-06 fixed: created workstream 777b17de\\u2026 for APPROVAL-WP-0005, wrote ID to APPROVAL-WP-0005-access-claim-fact-contract.md\",\n \" + task APPROVAL-WP-0005-T01 \\u2192 24bf384a\\u2026\",\n \" + task APPROVAL-WP-0005-T02 \\u2192 3275354d\\u2026\",\n \" + task APPROVAL-WP-0005-T03 \\u2192 362bfe75\\u2026\",\n \"brief: .custodian-brief.md updated\",\n \"push: pushed\"\n ],\n \"summary\": {\n \"fail\": 0,\n \"automation_error\": 0,\n \"warn\": 7,\n \"info\": 0\n },\n \"result\": \"warn\"\n}\n"
}

View file

@ -0,0 +1,28 @@
{
"go_race": {
"command": "go test -race -count=1 ./...",
"module": "adapters/go/approvalfact",
"result": "passed"
},
"go_vet": "passed",
"producer_golden_native_vectors": 14,
"producer_claim_cases": 24,
"transport": "only duplicate/nonfinite bodies tested here; HTTP transport negatives remain Access owner",
"python_differential": {
"command": "python3 scripts/check_go_approvalfact.py",
"matched_exact_canonical_bytes_and_digest": 14114,
"seed": 20261016,
"result": "passed"
},
"python_regressions": {
"command": "python3 -m pytest -q tests/test_access_claim_vectors.py tests/test_human_control.py tests/test_claim_contract.py tests/test_tenant_provenance.py",
"passed": 44
},
"retained_preparation_failures": [
"Initial go1.23 module selector could not find toolchain; module aligned to existing Access Go1.26.7, no added runtime",
"Shared default Go cache sandbox write refusal; authorized source test retry completed"
],
"combined_patch_check_exit": 0,
"incremental_patch_check_exit": 0,
"native_accepted": false
}

View file

@ -0,0 +1,65 @@
# Approval exact-consume source provenance
Prepared by the approval-engine worker, with its AGENTS.md and INTENT.md loaded,
in `/tmp/netkingdom-approval-reference-20261016`. Canonical owner source remained
unchanged and clean at `9491d1d3a7b6554fa04f8dc06f65d50e3d6ee4e1`.
This is source preparation and owner technical judgement, not a formal delegated
review, native approval or independently accepted deployment. The new owner work
record must be integrated before a formal review is recorded.
The existing authoritative consume CAS, durable transactional outbox,
ExecutionConfirmationClient and hardened fixed-origin transport already supply
the factual consumer boundary. A signed portable consume receipt is absent,
but adding another signer/service is unnecessary for the independently
authenticated mediator. The reachable source gap was discarded consume caller
identity and insufficient standalone act/PDP correspondence in the use event.
The patch passes HTTP-verified Identity to consume and atomically retains bounded
consumer metadata, native binding, PDP digest/path alongside existing full
request/decision and threshold evidence. Top-level actor remains the approved
initiator. Caller JSON cannot replace verified consumer provenance. Internal
calls retain null, retries preserve the first event, and historical rows remain
unchanged. Existing response/claim fields and schema version are unchanged.
INTENT basis: authenticated consumable object, exact binding and local atomic
evidence. It supplies facts and creates no new permission decision.
`implementation.patch`, `manifest.json`, `validation.json` and `patch-check.json`
pin the exact deliverable. Patch SHA256:
`a6bf77fa8b6916f423db7832f475e38747b828dd632a88f9631131e28e3230ee`.
44 focused tests passed. Full suite: 277 passed and one failed deployment-evidence
image pin check; the identical failure was reproduced on an untouched baseline.
Historical release/native evidence was preserved. No real token, approval,
OpenBao, native side effect, deployment or migration was used.
The scoped demand from CUST-WP-0080 is reconciled into WP0002 without promoting
all residuals. New WP0004 tracks the bounded source delivery and pending canonical
review/integration. The coordinator handles canonical sync after independent
review. Hub progress logging has its request/receipt here; no new workplan was
registered from the temporary checkout.
Native acceptance requires the existing owner interfaces:
- Approval T01: exact KeyCape issuer/audience/scope/tenant provenance receipt and
human-authorized release/migration with native verified entry/readback. Current
source identity tests do not prove issuer admission or deployment.
- Approval T04 / Audit: admit the refined source payload, drain actual lifecycle
rows and independently read receiver event ID/content; reconcile counts,
duplicate/lag/boundary handling, silence and scoped bearer revocation. Existing
local atomicity cannot prove omission resistance under source compromise.
- Approval T05 / Platform / Secrets: name actual served PEP revision/route and
actual independently authenticated read/consume client; establish trusted server
transport/custody/ingress. Validate fresh exact claim and signed Access decision,
approved native act, approval-free/full request bindings and immutable operation
plan before CAS. Preserve live one-shot journal admission, deadlines, unknown
outcomes, independently confirmed cleanup and approved recovery.
- Secrets and Access retain strict downstream consumption correspondence,
published policy/action/initiating-principal representation admission and
producer-compatible signed-decision trust. The outbox row does not validate
that a supplied decision ID exists or authorize a protected operation.
The native proof must bind exact source/image/config, identity, operation/body,
CAS evidence, actual protected effect, event/source/receiver correspondence and
cleanup. Wrong actor/tenant/body/decision, expiry, replay, unavailability and
consume-before-effect failure are required refusals. Fixture success is never
reported as native acceptance. The existing deployment pin/evidence discrepancy
must be reconciled by its owner from real release evidence before rollout.

View file

@ -0,0 +1,60 @@
---
id: APPROVAL-WP-0004
type: workplan
title: "Retain exact authenticated consume source provenance"
domain: infotech
repo: approval-engine
status: active
flavor: implementation
owner: codex
topic_slug: netkingdom
created: "2026-10-16"
updated: "2026-10-16"
depends_on: []
state_hub_workstream_id: "688edc60-a179-5618-90f1-468aadc2af58"
---
Explicit NetKingdom target demand under CUST-WP-0080 selects the source evidence
subset of APPROVAL-WP-0002-T01/T04/T05. INTENT basis: authenticated consumable
object, exact binding and atomic local evidence. Existing authoritative CAS,
confirmation transport and audit adapter are reused. No second approval/PDP
service, portable signer, foreign owner review or live action is added.
## Preserve verified consumer and approved operation in the use source row
```task
id: APPROVAL-WP-0004-T01
status: done
priority: high
state_hub_task_id: "b0b0a5a9-f7e7-508b-96d0-4b02457b16fc"
```
Source implementation supplies the HTTP-verified Identity to consume and writes
its bounded metadata plus native act/PDP bindings into the existing atomic use
outbox. Body-provided provenance is ignored, internal calls retain null, original
idempotent evidence is immutable, and historical rows remain untouched. No DB
schema change, response/claim widening or identity scope change is needed.
Seven new source tests cover signature-verified HTTP consumption, restart,
adapter preservation, spoofed fields, denied identities, retry immutability and
rollback. Source checks do not establish native acceptance.
## Integrate independently reviewed source and synchronize work records
```task
id: APPROVAL-WP-0004-T02
status: todo
priority: high
state_hub_task_id: "2b932ef8-e143-5bb7-856e-4cba4fb22c09"
```
The Custodian coordinator independently reviews the exact patch/manifest, then
integrates and synchronizes the canonical owner record. Temporary-checkout work
is not a canonical synchronized record or formal delegated-owner assent.
Existing native delivery obligations remain live under APPROVAL-WP-0002:
T01 exact issuer/profile and release/migration, T04 admitted lifecycle source
delivery/reconciliation, T05 named served PEP consumption before protected effect.
Platform owns mediator transport/identity/custody, the one-shot journal and native
effect; Secrets owns its actual strict handoff and task-scoped backend. Access
owns the signed decision and exact request/action/representation binding. No
claim that an isolated source test closes any of these gates is made.

View file

@ -0,0 +1,288 @@
diff --git a/approval_engine/api.py b/approval_engine/api.py
index 607ff19..440e4ac 100644
--- a/approval_engine/api.py
+++ b/approval_engine/api.py
@@ -176,6 +176,7 @@ class App:
approval_id,
data.get("request_digest"),
decision_id=data.get("decision_id"),
+ consumer=identity,
)
if "check" in path or path.endswith("/authorize"):
return 404, {"error": "not_found", "message": "no such surface"}
diff --git a/approval_engine/store.py b/approval_engine/store.py
index c30decc..eb02a24 100644
--- a/approval_engine/store.py
+++ b/approval_engine/store.py
@@ -18,6 +18,7 @@ from pathlib import Path
from typing import Any, Callable
from uuid import uuid4
+from .auth import Identity
from .binding import binding_digest, canonical_binding, require_digest
from .errors import (
Conflict,
@@ -750,6 +751,7 @@ class Engine:
request_digest: str | None,
*,
decision_id: str | None = None,
+ consumer: Identity | None = None,
) -> dict[str, Any]:
"""Atomically spend an approval for one decision-bound request.
@@ -819,6 +821,19 @@ class Engine:
actor=row["actor"],
extra={
"binding_digest": row["binding_digest"],
+ "binding": json.loads(row["binding_json"]),
+ "pdp_digest": row["pdp_digest"],
+ "pdp_path": bool(row["pdp_path"]),
+ # Only the HTTP boundary supplies an authenticated identity.
+ # Internal/legacy calls explicitly leave provenance unknown.
+ "consumer": ({
+ "subject_id": consumer.subject,
+ "issuer": consumer.issuer,
+ "principal_type": consumer.principal_type,
+ "tenant": consumer.tenant,
+ "tenant_source": consumer.tenant_source,
+ "evidence_ref": consumer.evidence_ref,
+ } if consumer is not None else None),
"request_digest": digest,
**({"decision_id": decision_id} if decision_id else {}),
"threshold": self._threshold_evidence(
diff --git a/docs/outbox-contract.md b/docs/outbox-contract.md
index a15bdc8..14295a3 100644
--- a/docs/outbox-contract.md
+++ b/docs/outbox-contract.md
@@ -130,3 +130,32 @@ where the identities are the point. A consumer that wants the threshold reads
Distinctness itself is a storage invariant rather than a recomputation:
`entries` is UNIQUE on `(approval_id, subject_id)`, so a repeat approver is
refused at insert.
+
+## Exact use provenance (source refinement, 2026-10-16)
+
+New `approval.use` rows additionally retain `details.binding` (the native
+five-field act), its existing `binding_digest`, nullable `pdp_digest` and
+explicit `pdp_path`. `request_digest` remains the full decision-bound request,
+and `decision_id` remains caller-supplied correlation, not a verified PDP verdict.
+These distinct digests must never be substituted for each other.
+
+`details.consumer` records the authenticated consume caller's `subject_id`,
+`issuer`, `principal_type`, exact `tenant`, nullable verified `tenant_source` and
+token-fingerprint `evidence_ref`. It comes solely from the HTTP authenticator;
+body fields cannot override it. Top-level `actor` retains its existing meaning:
+the actor captured on the approved act. Consumer provenance distinguishes the
+service spending the object from that initiating actor. Bearer values, scopes,
+roles and assurance are not copied into this record.
+
+In-process calls without an authenticated caller record `consumer: null`.
+Existing outbox rows remain unchanged; missing/null consumer evidence cannot be
+backfilled as authenticated. Same-digest retries preserve the first use row and
+never replace its original consumer or decision correspondence. All fields are
+inserted atomically with the consumption CAS, survive restart, and pass unchanged
+through the existing asynchronous audit adapter. No schema migration is needed.
+
+This source evidence is not a portable signed receipt, execution grant or
+server-identity proof. Consumer confirmation still uses the existing trusted
+authenticated read/consume transport and a separate live execution journal.
+Audit source admission, deployed issuer/profile, lifecycle readback and actual
+served-PEP proof remain APPROVAL-WP-0002-T01/T04/T05 native gates.
diff --git a/tests/test_consume_provenance.py b/tests/test_consume_provenance.py
new file mode 100644
index 0000000..f2b5d6a
--- /dev/null
+++ b/tests/test_consume_provenance.py
@@ -0,0 +1,110 @@
+"""Source evidence binds authenticated consumer, approved act and PDP digest."""
+import json
+
+import pytest
+
+from approval_engine.api import App, call
+from approval_engine.audit import audit_envelope
+from approval_engine.store import Engine
+from tests.conftest import FROZEN, binding, validity
+from tests.test_auth import _jwt
+from tests.test_tenant_provenance import authenticator
+
+FULL = "sha256:" + "ab" * 32
+FREE = "sha256:" + "cd" * 32
+
+
+def approved(engine):
+ obj = engine.create(binding(), validity(), pdp_digest=FREE, pdp_path=True,
+ human_control=True)
+ engine.add_entry(obj.id, "human:founder", principal_type="human")
+ return obj
+
+
+def token(private, **overrides):
+ claims = dict(sub="service:mediator", tenant="tenant:platform",
+ principal_type="service", tenant_source="registration",
+ scope="approval:consume")
+ claims.update(overrides)
+ return _jwt(private, **claims)
+
+
+def consume(app, obj, bearer, **body):
+ return call(app, "POST", f"/v1/approvals/{obj.id}/consume",
+ {"request_digest": FULL, "decision_id": "decision:original", **body},
+ authorization="Bearer " + bearer)
+
+
+def uses(engine):
+ return [r for r in engine.undrained() if r["class"] == "use"]
+
+
+def test_authenticated_consumer_and_exact_binding_survive_restart_and_drain(tmp_path):
+ private, auth = authenticator()
+ path = tmp_path / "approval.sqlite"
+ engine = Engine(path, clock=lambda: FROZEN)
+ obj = approved(engine)
+ bearer = token(private)
+ status, result = consume(App(engine, auth), obj, bearer,
+ consumer={"subject_id": "spoofed"}, pdp_digest="spoofed")
+ assert status == 200 and result["idempotent"] is False
+ event = uses(engine)[0]
+ details = event["payload"]["details"]
+ assert event["payload"]["actor"] == binding()["actor"]
+ assert details["binding"] == binding()
+ assert details["binding_digest"] == obj.binding_digest
+ assert details["pdp_digest"] == FREE and details["pdp_path"] is True
+ assert details["request_digest"] == FULL
+ assert details["decision_id"] == "decision:original"
+ assert details["consumer"] == {
+ "subject_id": "service:mediator", "issuer": "https://keycape.example",
+ "principal_type": "service", "tenant": "tenant:platform",
+ "tenant_source": "registration", "evidence_ref": auth.authenticate("Bearer " + bearer).evidence_ref,
+ }
+ assert bearer not in json.dumps(event)
+ assert "consumer" not in json.dumps(engine.claim(obj.id))
+ engine.close()
+ engine = Engine(path, clock=lambda: FROZEN, auto_migrate=False)
+ assert uses(engine) == [event]
+ # A second authenticated caller cannot rewrite the first consumer evidence.
+ status, retry = consume(App(engine, auth), obj, token(private, sub="service:retry"),
+ decision_id="decision:other")
+ assert status == 200 and retry["idempotent"] is True
+ assert retry["decision_id"] == "decision:original"
+ assert uses(engine) == [event]
+ delivered = []
+ engine.drain(lambda payload: delivered.append(audit_envelope(payload)))
+ use = next(e for e in delivered if e["type"] == "approval.use")
+ assert use["id"] == event["event_id"]
+ assert use["data"]["details"] == details
+ engine.close()
+
+
+@pytest.mark.parametrize("overrides,expected", [
+ ({"tenant": "tenant:foreign"}, 403),
+ ({"principal_type": "human"}, 403),
+ ({"scope": "approval:read"}, 403),
+ ({"tenant_source": "spoofed"}, 401),
+])
+def test_unadmitted_consumer_cannot_create_evidence(engine, overrides, expected):
+ private, auth = authenticator()
+ obj = approved(engine)
+ assert consume(App(engine, auth), obj, token(private, **overrides))[0] == expected
+ assert uses(engine) == [] and engine.get(obj.id).status == "approved"
+
+
+def test_outbox_failure_rolls_back_consumer_and_spend(engine):
+ private, auth = authenticator()
+ obj = approved(engine)
+ engine.fail_outbox = True
+ assert consume(App(engine, auth), obj, token(private))[0] == 503
+ assert engine.get(obj.id).status == "approved" and uses(engine) == []
+ engine.fail_outbox = False
+ assert consume(App(engine, auth), obj, token(private, sub="service:recovered"))[0] == 200
+ assert uses(engine)[0]["payload"]["details"]["consumer"]["subject_id"] == "service:recovered"
+
+
+def test_internal_calls_do_not_invent_authenticated_consumer(engine):
+ obj = approved(engine)
+ engine.consume(obj.id, FULL)
+ assert uses(engine)[0]["payload"]["details"]["consumer"] is None
diff --git a/workplans/APPROVAL-WP-0002-production-readiness-and-consumer-adoption.md b/workplans/APPROVAL-WP-0002-production-readiness-and-consumer-adoption.md
index e3ff5ca..856ebc7 100644
--- a/workplans/APPROVAL-WP-0002-production-readiness-and-consumer-adoption.md
+++ b/workplans/APPROVAL-WP-0002-production-readiness-and-consumer-adoption.md
@@ -34,6 +34,15 @@ Current status: blocked after the 2026-10-04 dependency review. T02, T03 and
T06 are complete. T01, T04 and T05 use `wait` for blocked task status; their
remaining owner receipts are specified in `docs/production-dependencies.md`.
+2026-10-16 target-architecture demand reconciliation: CUST-WP-0080 explicitly
+selects necessary authenticated-consume/provenance/audit and exact served-PEP
+interfaces from T01/T04/T05. APPROVAL-WP-0004 implements only the reachable
+source use-evidence gap: verified consuming identity and approved act/PDP binding
+in the existing transactional outbox. This scoped implementation demand does
+not activate unrelated residuals or authorize credentials, migration, rollout,
+production approvals or native effects. T01/T04/T05 remain wait for their
+existing independently owned native receipts; this workplan remains residual.
+
Review completed 2026-09-01. The plan is active. Production mode will verify
KeyCape JWT signatures and exact issuer/audience/scopes; local caller-supplied
identity never becomes authenticated evidence. SQLite remains the first
diff --git a/workplans/APPROVAL-WP-0004-exact-consume-source-provenance.md b/workplans/APPROVAL-WP-0004-exact-consume-source-provenance.md
new file mode 100644
index 0000000..b9bc3fc
--- /dev/null
+++ b/workplans/APPROVAL-WP-0004-exact-consume-source-provenance.md
@@ -0,0 +1,57 @@
+---
+id: APPROVAL-WP-0004
+type: workplan
+title: "Retain exact authenticated consume source provenance"
+domain: infotech
+repo: approval-engine
+status: active
+flavor: implementation
+owner: codex
+topic_slug: netkingdom
+created: "2026-10-16"
+updated: "2026-10-16"
+depends_on: []
+---
+
+Explicit NetKingdom target demand under CUST-WP-0080 selects the source evidence
+subset of APPROVAL-WP-0002-T01/T04/T05. INTENT basis: authenticated consumable
+object, exact binding and atomic local evidence. Existing authoritative CAS,
+confirmation transport and audit adapter are reused. No second approval/PDP
+service, portable signer, foreign owner review or live action is added.
+
+## Preserve verified consumer and approved operation in the use source row
+
+```task
+id: APPROVAL-WP-0004-T01
+status: done
+priority: high
+```
+
+Source implementation supplies the HTTP-verified Identity to consume and writes
+its bounded metadata plus native act/PDP bindings into the existing atomic use
+outbox. Body-provided provenance is ignored, internal calls retain null, original
+idempotent evidence is immutable, and historical rows remain untouched. No DB
+schema change, response/claim widening or identity scope change is needed.
+Seven new source tests cover signature-verified HTTP consumption, restart,
+adapter preservation, spoofed fields, denied identities, retry immutability and
+rollback. Source checks do not establish native acceptance.
+
+## Integrate independently reviewed source and synchronize work records
+
+```task
+id: APPROVAL-WP-0004-T02
+status: todo
+priority: high
+```
+
+The Custodian coordinator independently reviews the exact patch/manifest, then
+integrates and synchronizes the canonical owner record. Temporary-checkout work
+is not a canonical synchronized record or formal delegated-owner assent.
+
+Existing native delivery obligations remain live under APPROVAL-WP-0002:
+T01 exact issuer/profile and release/migration, T04 admitted lifecycle source
+delivery/reconciliation, T05 named served PEP consumption before protected effect.
+Platform owns mediator transport/identity/custody, the one-shot journal and native
+effect; Secrets owns its actual strict handoff and task-scoped backend. Access
+owns the signed decision and exact request/action/representation binding. No
+claim that an isolated source test closes any of these gates is made.

View file

@ -0,0 +1,5 @@
{
"exit_code": 0,
"stdout": "",
"stderr": ""
}

View file

@ -0,0 +1 @@
{"workplan_id":"4fa25ad5-f5d0-5592-aa59-085f8ee3edaf","id":"c6bddc94-a264-4c82-8b28-6507e2019624","topic_id":null,"task_id":null,"decision_id":null,"event_type":"note","summary":"approval-engine owner source preparation under CUST-WP-0080: exact authenticated consuming identity and approved act/PDP binding retained atomically in existing approval.use outbox. Isolated patch/manifest in docs/changes/netkingdom-target-2026-10-16/approval-reference. 44 focused passed; full 277 passed, one unchanged baseline deployment evidence pin mismatch reproduced. Canonical review/integration/sync pending coordinator; APPROVAL-WP-0002 native gates remain open; no credential/deploy/native action.","detail":null,"author":"codex","session_id":null,"created_at":"2026-10-16T00:06:37.193148Z","workstream_id":"4fa25ad5-f5d0-5592-aa59-085f8ee3edaf"}

View file

@ -0,0 +1 @@
{"summary": "approval-engine owner source preparation under CUST-WP-0080: exact authenticated consuming identity and approved act/PDP binding retained atomically in existing approval.use outbox. Isolated patch/manifest in docs/changes/netkingdom-target-2026-10-16/approval-reference. 44 focused passed; full 277 passed, one unchanged baseline deployment evidence pin mismatch reproduced. Canonical review/integration/sync pending coordinator; APPROVAL-WP-0002 native gates remain open; no credential/deploy/native action.", "event_type": "note", "author": "codex", "workplan_id": "4fa25ad5-f5d0-5592-aa59-085f8ee3edaf"}

View file

@ -0,0 +1,57 @@
--- a/workplans/APPROVAL-WP-0004-exact-consume-source-provenance.md
+++ b/workplans/APPROVAL-WP-0004-exact-consume-source-provenance.md
@@ -4,7 +4,7 @@
title: "Retain exact authenticated consume source provenance"
domain: infotech
repo: approval-engine
-status: active
+status: finished
flavor: implementation
owner: codex
topic_slug: netkingdom
@@ -42,19 +42,40 @@
```task
id: APPROVAL-WP-0004-T02
-status: todo
+status: done
priority: high
state_hub_task_id: "2b932ef8-e143-5bb7-856e-4cba4fb22c09"
```
-The Custodian coordinator independently reviews the exact patch/manifest, then
-integrates and synchronizes the canonical owner record. Temporary-checkout work
-is not a canonical synchronized record or formal delegated-owner assent.
+The Custodian coordinator reviewed and integrated the exact source patch
+`a6bf77fa8b6916f423db7832f475e38747b828dd632a88f9631131e28e3230ee` as commit
+`477c683991fda3c01e2af98a18f5a8719ee9dbc9`. Canonical source hashes and integration
+are recorded in the-custodian's
+`docs/changes/netkingdom-target-2026-10-16/approval-reference/canonical-integration.json`.
+Normal State Hub sync/publication is recorded in the same change directory's
+`sync-session-61857.json`: bindings synchronized 5/5, source commit pushed, zero
+failures, zero automation errors and nine warnings. The generated-only writeback
+commit refusal remains recorded in that receipt; generated identifiers are
+retained. Published origin HEAD was independently read back as the exact commit
+above on 2026-10-16. This completes scoped source integration/publication, not
+formal delegated-owner assent or native acceptance. The closure-file update
+itself still follows the coordinator's normal review and synchronization.
Existing native delivery obligations remain live under APPROVAL-WP-0002:
T01 exact issuer/profile and release/migration, T04 admitted lifecycle source
delivery/reconciliation, T05 named served PEP consumption before protected effect.
Platform owns mediator transport/identity/custody, the one-shot journal and native
-effect; Secrets owns its actual strict handoff and task-scoped backend. Access
+effect; Secrets owns implementation of the strict handoff and task-scoped
+backend. The strict task handoff is not implemented at Secrets canonical
+`c80a944105a00220cd3c1a007709e72d830dd08d`
+and remains its next implementation work. Access
owns the signed decision and exact request/action/representation binding. No
claim that an isolated source test closes any of these gates is made.
+
+No scoped source work remains in APPROVAL-WP-0004. The native obligations above
+were live in APPROVAL-WP-0002 before this work and remain there under their
+existing identifiers and wait statuses; no new residual record is needed and
+no residual implementation is promoted by this closure. Further implementation
+of a necessary WP0002 residual must be explicitly selected under the continuing
+CUST-WP-0080 target demand and recorded with its precise owner/action scope;
+credential, rollout and native effect steps retain their separate authority gates.

View file

@ -0,0 +1,20 @@
{
"focused": {
"command": "python3 -m pytest -q tests/test_consume_provenance.py tests/test_outbox.py tests/test_execution_confirmation.py",
"passed": 44
},
"full": {
"command": "python3 -m pytest -q",
"passed": 277,
"failed": 1,
"failure": "tests/test_deploy_manifest.py::test_pinned_image_schema_drift_is_acknowledged",
"reason": "manifest image digest sha256:16e5d222d58e179f4836f649e8f8128321a8b644d29dc426b4d21a65ff97845d differs from historical release evidence digest sha256:251941a5cb2724b57cc32cff6b693b1ab0be695bee4f56f02d51961189c0fa49"
},
"baseline_failure_reproduced": {
"checkout": "/tmp/netkingdom-approval-baseline-20261016",
"command": "python3 -m pytest -q tests/test_deploy_manifest.py::test_pinned_image_schema_drift_is_acknowledged",
"failed": 1,
"same_mismatch": true
},
"diff_check": "passed"
}

View file

@ -0,0 +1,55 @@
# Approval authoritative timestamp precision repair
Frozen source repair under APPROVAL-WP-0006-T01, base
`3485415b823faf4f3b682079195e186666b0ed2b`. Isolated source:
`/tmp/netkingdom-approval-timestamp-precision-20261016`.
Canonical source, prior WP0005 closure and registrar-generated identifiers remain
untouched. Exact observed owner dirt is preserved in owner-dirty-baseline.patch.
The coordinator counterexample demonstrates a real validity defect: clock .750
was rounded to .000 and consumed an approval expiring at .500. The same rounding
made legitimate immediate consumption evidence appear before Access's precise
signed NotBefore. The repair retains actual aware UTC microseconds in utc_now
and ISO serialization. First consumption samples exactly once after SQLite's
write lock is acquired and uses that one instant for validity, immutable receipt,
updated_at and the use outbox's occurrence/creation time. No Access backdating,
consumer tolerance, caller sleep, schema change or new approval protocol exists.
Historical whole-second rows/readback and same-digest idempotent receipts retain
their original timestamps/decision IDs without fabricated precision. All new
source timestamps, including claims/freshness, preserve clock precision. The
existing Go helper already accepts microseconds; its code is unchanged, and only
its README's old whole-second producer statement is corrected.
Validation: 89 focused tests pass, including actual SQLite lock waits crossing
expiry, immediate fractional receipt/readback/restart, one sampled clock and
identical receipt/outbox time, unchanged old evidence and failed-outbox rollback.
Full source suite: 298 pass, one known historical release-evidence/image-pin
mismatch remains. Original regressions failed five cases before repair. An
initial repaired test tried issuing an already expired approval and correctly
failed; its fixture now issues before expiry and then advances. These outcomes
remain recorded instead of being rewritten into success.
`implementation.patch` SHA256:
`74eb0ff67d14508c2a2cee14d055790321ee171a96d5290ad6d037ce8f61dbcd`.
`approval_engine/store.py` SHA256:
`866b275ed2d844d0aa9090ce9899ce955c6bfe32a493c2645c86e72efa343e86`.
The original standalone repair is frozen independently of later temporal review.
`owner-review-record.patch` applies after it, recording T02 progress and the
Approval-owned formal review in the owner repo; no canonical write is performed.
The supplementary review approves Approval facts/time only for exact Access R3
full patch `46bfeb706d3a88bf6054309cc9303eb360a91e57dda3b0fcbb7b80d551a75db6`.
All 31 frozen source hashes match; independent temporal/retained-registry HTTP
race checks pass. Signed claim-free DENY supplies authenticated normalized facts
before issue; final source join compares that approved act/PDP binding without
rewriting the original claim. Exact operation lifetime must fit original/fresh
fact bounds. Default freshness30 cannot cover backend30 plus cleanup5;
fixture freshness120 is explicit synthetic configuration, never a native grant.
Prior R1 review and WP0005 closure remain exact historical records. Immediate
strict CAS and whole-path remeasurement use the final separately pinned repaired
Approval source, Access R3 and Secrets successor; their result is not assumed
here. Native issuer/profile, source/custody/config/image admission, actual audit
receiver and served PEP/CAS/journal/effect/cleanup remain the existing WP0002
T01/T04/T05 and other-owner obligations. No authority promotion is recorded.

View file

@ -0,0 +1,13 @@
{
"patch": "review-sha256-prefix.patch",
"patch_sha256": "sha256:7ff222f5a0968d8b580382d21246c987f03990aa152aec6f61edeb3a367963be",
"original_git_blob": "deefaac30c988de61ee26a08f29482ae76b39a0b",
"formatted_git_blob": "4a0b3e3404a36544f7e90e974a76bd0aab946783",
"files_sha256": {
"updated-review.json": "sha256:2bfc6122456737918f5cf5f2c5f62eb30886b7ea911b601589ab08fc6225e98c",
"owner-reaffirmation.json": "sha256:bdaa2bd086d0d93e3d799cab6f7f6b59447572a88418003999fc2aa481cfa4a5",
"review-sha256-prefix.patch": "sha256:7ff222f5a0968d8b580382d21246c987f03990aa152aec6f61edeb3a367963be",
"validation.json": "sha256:ee50e4ca1a5e060e9d227bbe3f4868396e05719286890c75965086de30bac1b6"
},
"canonical_mutated_by_owner": false
}

View file

@ -0,0 +1,13 @@
{
"reviewer": "approval-engine-owner (agent approval-engine, codex)",
"decision": "approved",
"comment": "APPROVAL-WP-0006-T02 supplemental source review formatting only. Seven explicit sha256: prefixes label existing public digest metadata in values and prose. Removing only that prefix restores the exact original review bytes; digest values, technical judgement, reviewed source revisions and authority exclusions are unchanged. The owner reaffirms the original Approval-only fact/time review and no native authority is promoted. This is a new narrow formatting delta; original frozen repair/review artifacts remain historical and immutable.",
"target": "docs/reviews/2026-10-16-fractional-consumption-temporal-approval-owner-review.json",
"original_review_sha256": "sha256:fd5a00c498940fcfeaf188bded42de2f55b2fd04d0f78f294cc00610f5af3a6b",
"formatted_review_sha256": "sha256:2bfc6122456737918f5cf5f2c5f62eb30886b7ea911b601589ab08fc6225e98c",
"format_patch_sha256": "sha256:7ff222f5a0968d8b580382d21246c987f03990aa152aec6f61edeb3a367963be",
"normal_scanner_result": "clean after explicit public digest labels; original blocked blob independently reproduced with unchanged pinned scanner",
"source_implementation_changed": false,
"canonical_mutated_by_owner": false,
"native_accepted": false
}

View file

@ -0,0 +1,46 @@
{
"reviewer": "approval-engine-owner (agent approval-engine, codex)",
"decision": "approved",
"comment": "INTENT Purpose (valid right now), The Claim Shape and Consumption Ordering: approved for bounded Approval source time precision repair and Approval-owned fact/temporal correspondence in exact Access R3 source. Work APPROVAL-WP-0006-T01/T02. Repair patch SHA256 sha256:74eb0ff67d14508c2a2cee14d055790321ee171a96d5290ad6d037ce8f61dbcd against 3485415b823faf4f3b682079195e186666b0ed2b; store.py SHA256 sha256:866b275ed2d844d0aa9090ce9899ce955c6bfe32a493c2645c86e72efa343e86. Access R3 full patch SHA256 sha256:46bfeb706d3a88bf6054309cc9303eb360a91e57dda3b0fcbb7b80d551a75db6, delta sha256:17ecf399c50c07845c545b31cad4022200eb20dfb760595aa76a271e9cee7521; all 31 frozen source hashes matched. This review does not assent to Access policy/other-owner behavior, native credentials/trust, deployment or effects.",
"reviewed_repair_patch_sha256": "sha256:74eb0ff67d14508c2a2cee14d055790321ee171a96d5290ad6d037ce8f61dbcd",
"reviewed_access_full_r3_sha256": "sha256:46bfeb706d3a88bf6054309cc9303eb360a91e57dda3b0fcbb7b80d551a75db6",
"reviewed_access_r2_to_r3_sha256": "sha256:17ecf399c50c07845c545b31cad4022200eb20dfb760595aa76a271e9cee7521",
"approval_time_findings": [
"utc_now and iso preserve actual aware microseconds; no schema or binding algorithm change",
"First consume samples one authoritative time only after BEGINIMMEDIATE obtains the lock; identical instant checks validity, persists receipt/update and creates use outbox timestamp",
"Expiry remains exclusive; actual clock .750 refuses expiry .500; post-lock expiry cannot borrow pre-lock admission",
"Whole-second old rows, readback and idempotent original decision/timestamp are preserved without fabricated precision; no unconsume, retry authority or tolerance",
"No Access NotBefore backdating, caller wait/sleep acceptance or consumer timing waiver is needed"
],
"access_fact_temporal_findings": [
"Signed claim-free DENY normalization receipt supplies existing producer-evaluated native act and approval-free digest before issue, never permission; requester consumer independently authenticates it",
"Actual retained registry normalization is source-owned and number-preserving; final join compares the approved act/PDP digest and refuses drift instead of refreshing old context",
"Original and newly fetched facts are validated separately; no mutation of original claim/context or either request digest",
"Exact immutable operation deadline must fit caller, original/fetched freshness and approval validity; decision is precise post-evaluation NotBefore to exact operation deadline",
"Entire remaining interval must cover declared backendTTL plus 5-second cleanup reserve and source maximum 120; this review does not approve that policy or native budget",
"Default Approval freshness 30 cannot satisfy minimum 30+5; fixture freshness 120 is explicit synthetic configuration, not a producer default flip or native grant"
],
"validation": {
"repair_focused_passed": 89,
"repair_full_passed": 298,
"repair_full_failed_preexisting": 1,
"baseline_counterexamples_failed": 5,
"access_independent_command": "go test -race -count=1 ./internal/decision ./cmd/access-engine -run TestTrusted",
"access_independent_result": "passed"
},
"retained_failures": [
"coordinator-counterexample.json documents canonical expired fractional approval consumed",
"Initial repair expiry test attempted already-expired issuance; repaired engine correctly refused; fixture corrected to issue before expiry then advance",
"Existing deployment pin/historical release evidence mismatch remains unchanged"
],
"prior_evidence": "WP0005 closure and6079edR1review remain exact historical evidence; this is a new precision task and new exactR3 review",
"remaining_gates": [
"Coordinator independent source integration/publication/synchronization at exact repair and Access/Secrets successor source pins",
"Actual immediate strict CAS/whole-path remeasurement must use unchanged precise signed NotBefore and no sleep/waiver",
"Native issuer/profile, CA/source/read credential/store tenant admission and schema/image/config rollout remain existing WP0002T01",
"Actual use event/audit receiver reconciliation remains WP0002T04",
"Served PEP original decision/request CAS before effect, live one-shot journal, deadlines and confirmed cleanup remain WP0002T05 and existing Secrets/Platform work"
],
"native_accepted": false,
"authority_promotion": false
}

View file

@ -0,0 +1,24 @@
{
"scanner_command": "python3 /home/worsch/repo-manager/src/repo_manager/secret_scan.py --path /tmp/approval-review-formatting-20261016 --binary /home/worsch/.local/lib/repo-manager/gitleaks/8.30.1/gitleaks",
"scanner_version": "8.30.1",
"scanner_sha256": "sha256:88f91962aa2f93ac6ab281d553b9e125f5197bbbce38f9f2437f7299c32e5509",
"before": {
"status": "blocked",
"scanned_blobs": 1,
"blocked_blob_ids": [
"deefaac30c988de61ee26a08f29482ae76b39a0b"
]
},
"after": {
"status": "clean",
"scanned_blobs": 1,
"blocked_blob_ids": [],
"formatted_blob_id": "4a0b3e3404a36544f7e90e974a76bd0aab946783"
},
"prefixes_added": 7,
"all_digest_bytes_preserved": true,
"all_other_bytes_preserved": true,
"JSON_valid": true,
"scanner_config_ignores_bypassed": false,
"canonical_mutated_by_owner": false
}

View file

@ -0,0 +1,303 @@
diff --git a/adapters/go/approvalfact/README.md b/adapters/go/approvalfact/README.md
index fdffd1f..1b67b64 100644
--- a/adapters/go/approvalfact/README.md
+++ b/adapters/go/approvalfact/README.md
@@ -36,7 +36,8 @@ Canonical float/string formatting follows Python source, including negative
floating zero, exponent switching/padding, HTML and U+2028/U+2029. Duplicate
object keys, nonfinite/overflow numbers, invalid UTF-8 and lone surrogates refuse.
Inputs are bounded to 1 MiB and 128 container levels. Timestamp precision is at
-most nanoseconds with strict zoned RFC3339; current producer emits whole seconds.
+most nanoseconds with strict zoned RFC3339; the precision-repaired Python
+producer preserves microseconds, while historical whole-second strings remain valid.
These explicit parser/resource limits fail closed, never normalize authority.
`go test -race ./...` checks the portable producer vectors, typed fact pairing,
diff --git a/approval_engine/store.py b/approval_engine/store.py
index eb02a24..e9444d9 100644
--- a/approval_engine/store.py
+++ b/approval_engine/store.py
@@ -103,11 +103,11 @@ def utc_now(clock: Callable[[], datetime] | None = None) -> datetime:
now = datetime.now(timezone.utc)
if now.tzinfo is None:
now = now.replace(tzinfo=timezone.utc)
- return now.astimezone(timezone.utc).replace(microsecond=0)
+ return now.astimezone(timezone.utc)
def iso(ts: datetime) -> str:
- return ts.astimezone(timezone.utc).replace(microsecond=0).isoformat()
+ return ts.astimezone(timezone.utc).isoformat()
def parse_iso(value: str) -> datetime:
@@ -768,7 +768,6 @@ class Engine:
):
raise Unprocessable("decision_id must be a non-empty string")
conn = self._conn()
- now = iso(self.now())
idempotent = False
try:
conn.execute("BEGIN IMMEDIATE")
@@ -794,7 +793,11 @@ class Engine:
if row["status"] != "approved":
conn.rollback()
raise Conflict(f"cannot consume from status {row['status']}")
- if self.now() < parse_iso(row["not_before"]) or self.now() >= parse_iso(row["expires_at"]):
+ # Lock acquisition can wait past a validity boundary. One post-lock
+ # instant is authoritative for both the check and its durable proof.
+ consumed_at = self.now()
+ now = iso(consumed_at)
+ if consumed_at < parse_iso(row["not_before"]) or consumed_at >= parse_iso(row["expires_at"]):
conn.rollback()
raise Conflict("cannot consume outside validity window")
if row["human_control"]:
@@ -819,6 +822,7 @@ class Engine:
"use",
approval_id,
actor=row["actor"],
+ observed_at=consumed_at,
extra={
"binding_digest": row["binding_digest"],
"binding": json.loads(row["binding_json"]),
@@ -911,13 +915,14 @@ class Engine:
*,
actor: str | None,
extra: dict[str, Any] | None = None,
+ observed_at: datetime | None = None,
) -> str:
if self.fail_outbox:
raise StoreUnavailable("outbox insert failed")
if event_class not in EVENT_CLASSES:
raise Unprocessable(f"unknown event class {event_class}")
event_id = str(uuid4())
- created = iso(self.now())
+ created = iso(observed_at if observed_at is not None else self.now())
resource = f"approval:{approval_id}" if approval_id else "approval-engine:heartbeat"
details = {"class": event_class, **(extra or {})}
if approval_id:
diff --git a/docs/approval-consumption.md b/docs/approval-consumption.md
index f85ab28..45cbb96 100644
--- a/docs/approval-consumption.md
+++ b/docs/approval-consumption.md
@@ -42,6 +42,24 @@ after consumption, the approval remains spent and a retry needs a new approval.
The response is mutation evidence, not a permission decision. It contains no
`effect`, `allow`, `deny`, or decision result.
+## Authoritative time and fractional precision
+
+New source preserves the actual aware UTC clock's microseconds rather than
+rounding down to whole seconds. The first consume samples one instant after
+`BEGIN IMMEDIATE` acquires its write lock, then uses that instant for the
+not-before/inclusive and expiry/exclusive check, persisted `consumed_at` and
+`updated_at`, and use-event occurrence/creation time. Lock wait cannot borrow
+an earlier validity instant or stamp evidence before actual admission.
+
+Existing whole-second ISO strings remain valid and are never backfilled with
+invented fractions. Idempotent responses and object readback retain the original
+recorded timestamp/decision exactly, even after expiry; they do not renew
+execution authority. The store schema, API keys, CAS/digest correspondence and
+no-unconsume rule are unchanged. Claim observation/freshness and other new
+source timestamps also retain actual clock precision. Consumers must parse
+aware ISO/RFC3339 timestamps including fractional seconds instead of assuming
+a fixed-width whole-second string. No clock skew or early-use tolerance is added.
+
## The claim response is not an `ActionAuthorization`
`GET /v1/approvals/{id}/claim` serves the **approval-claim** envelope defined in
diff --git a/tests/test_timestamp_precision.py b/tests/test_timestamp_precision.py
new file mode 100644
index 0000000..42fb5bc
--- /dev/null
+++ b/tests/test_timestamp_precision.py
@@ -0,0 +1,130 @@
+"""Actual source clock, locking and original immutable receipt precision."""
+from datetime import timedelta, timezone
+import sqlite3
+import threading
+from concurrent.futures import ThreadPoolExecutor
+
+import pytest
+
+from approval_engine.errors import Conflict, StoreUnavailable
+from approval_engine.store import Engine, iso, utc_now
+from tests.conftest import FROZEN, binding
+
+DIGEST = "sha256:" + "ab" * 32
+
+
+def issue(engine, start, end):
+ obj = engine.create(binding(), {"not_before": start.isoformat(), "expires_at": end.isoformat()})
+ return engine.add_entry(obj.id, "human", principal_type="human")
+
+
+def uses(engine):
+ return [row for row in engine.undrained() if row["class"] == "use"]
+
+
+def test_clock_and_iso_preserve_aware_precision_and_legacy_seconds():
+ now = FROZEN.replace(microsecond=750123)
+ offset = now.astimezone(timezone(timedelta(hours=2)))
+ assert utc_now(lambda: offset) == now
+ assert iso(offset) == "2026-08-29T12:00:00.750123+00:00"
+ assert iso(FROZEN) == "2026-08-29T12:00:00+00:00"
+
+
+def test_fractional_expiry_refuses_actual_canonical_counterexample():
+ engine = Engine(clock=lambda: FROZEN)
+ obj = issue(engine, FROZEN-timedelta(seconds=1), FROZEN.replace(microsecond=500000))
+ engine.clock = lambda: FROZEN.replace(microsecond=750000)
+ assert engine.claim(obj.id)["valid_now"] is False
+ with pytest.raises(Conflict):
+ engine.consume(obj.id, DIGEST, decision_id="decision:original")
+ assert uses(engine) == []
+
+
+def test_immediate_fractional_receipt_restart_and_outbox_use_one_instant(tmp_path):
+ current = [FROZEN.replace(microsecond=750123)]
+ path = tmp_path/"approval.sqlite"
+ engine = Engine(path, clock=lambda: current[0])
+ obj = issue(engine, FROZEN.replace(microsecond=700000), FROZEN+timedelta(seconds=1))
+ samples = []
+ def clock():
+ value = current[0] + timedelta(microseconds=len(samples))
+ samples.append(value)
+ return value
+ engine.clock = clock
+ result = engine.consume(obj.id, DIGEST, decision_id="decision:original")
+ assert samples == [current[0]]
+ assert result["consumed_at"] == current[0].isoformat()
+ assert result["consumed_at"] >= FROZEN.replace(microsecond=700001).isoformat()
+ event = uses(engine)[0]
+ assert event["created_at"] == event["payload"]["observed_at"] == result["consumed_at"]
+ engine.close()
+ engine = Engine(path, clock=lambda: FROZEN+timedelta(days=1), auto_migrate=False)
+ assert engine.get(obj.id).as_dict()["consumption"]["consumed_at"] == result["consumed_at"]
+ retry = engine.consume(obj.id, DIGEST, decision_id="decision:new")
+ assert retry == {**result, "idempotent": True}
+ assert uses(engine) == [event]
+ engine.close()
+
+
+@pytest.mark.parametrize("after,accepted", [(450000, True), (750000, False)])
+def test_consume_samples_after_real_sqlite_lock_wait(tmp_path, after, accepted):
+ current = [FROZEN.replace(microsecond=250000)]
+ path = tmp_path/"approval.sqlite"
+ engine = Engine(path, clock=lambda: current[0])
+ obj = issue(engine, FROZEN-timedelta(seconds=1), FROZEN.replace(microsecond=500000))
+ entered = threading.Event()
+ initialized = threading.Event()
+ start = threading.Event()
+ samples = []
+ def consume():
+ conn = engine._conn()
+ conn.set_trace_callback(lambda statement: entered.set() if statement == "BEGIN IMMEDIATE" else None)
+ initialized.set()
+ assert start.wait(2)
+ def clock():
+ samples.append(current[0])
+ return current[0]
+ engine.clock = clock
+ try:
+ return engine.consume(obj.id, DIGEST, decision_id="decision:original")
+ finally:
+ engine.close()
+ with ThreadPoolExecutor(max_workers=1) as pool:
+ future = pool.submit(consume)
+ assert initialized.wait(2)
+ lock = sqlite3.connect(path)
+ lock.execute("BEGIN IMMEDIATE")
+ start.set()
+ assert entered.wait(2)
+ current[0] = FROZEN.replace(microsecond=after)
+ lock.commit()
+ lock.close()
+ if accepted:
+ assert future.result(timeout=2)["consumed_at"] == current[0].isoformat()
+ else:
+ with pytest.raises(Conflict):
+ future.result(timeout=2)
+ assert samples == [current[0]]
+ assert len(uses(engine)) == int(accepted)
+ engine.close()
+
+
+def test_old_second_precision_receipt_and_payload_are_never_backfilled(tmp_path):
+ engine = Engine(tmp_path/"old.sqlite", clock=lambda: FROZEN)
+ obj = issue(engine, FROZEN-timedelta(seconds=1), FROZEN+timedelta(seconds=1))
+ original = engine.consume(obj.id, DIGEST, decision_id="decision:old")
+ event = uses(engine)[0]
+ assert original["consumed_at"] == "2026-08-29T12:00:00+00:00"
+ engine.clock = lambda: FROZEN + timedelta(days=1, microseconds=123456)
+ assert engine.consume(obj.id, DIGEST, decision_id="decision:new") == {**original, "idempotent": True}
+ assert uses(engine) == [event]
+
+
+def test_fractional_use_outbox_failure_rolls_back(engine):
+ engine.clock = lambda: FROZEN.replace(microsecond=123456)
+ obj = issue(engine, FROZEN, FROZEN+timedelta(seconds=1))
+ engine.fail_outbox = True
+ with pytest.raises(StoreUnavailable):
+ engine.consume(obj.id, DIGEST)
+ assert engine.get(obj.id).consumed_at is None
+ assert uses(engine) == []
diff --git a/workplans/APPROVAL-WP-0006-fractional-consumption-time.md b/workplans/APPROVAL-WP-0006-fractional-consumption-time.md
new file mode 100644
index 0000000..be9ab93
--- /dev/null
+++ b/workplans/APPROVAL-WP-0006-fractional-consumption-time.md
@@ -0,0 +1,55 @@
+---
+id: APPROVAL-WP-0006
+type: workplan
+title: "Preserve fractional authoritative approval and consumption time"
+domain: infotech
+repo: approval-engine
+status: active
+flavor: implementation
+owner: codex
+topic_slug: netkingdom
+created: "2026-10-16"
+updated: "2026-10-16"
+depends_on: []
+---
+
+Explicit CUST-WP-0080 precision defect demand: actual clock .750 was rounded to
+.000, accepting consume beyond a .500 expiry and recording evidence earlier than
+the actual signed decision. INTENT basis: valid right now, exact-bound atomic
+consumption and faithful source evidence. Fix source time, not Access backdating
+or a consumer waiver. This does not promote native issuer/deployment authority.
+
+## Preserve clock precision and one post-lock consumption instant
+
+```task
+id: APPROVAL-WP-0006-T01
+status: done
+priority: high
+```
+
+Preserve aware UTC microseconds through clock/ISO formatting. After acquisition
+of the SQLite consume lock, sample one time for validity, stored consumption
+receipt/update and use-event occurrence. Preserve old second-precision rows,
+original idempotent receipt/decision and local transactional atomicity.
+
+Seven added regressions: baseline five failed/two passed; repaired 89 focused
+checks pass. Full source suite: 298 passed, one pre-existing deployment pin vs
+historical release-evidence mismatch retained. One initial test attempted issue
+after expiry and was corrected to issue before expiry, then advance the clock;
+the repaired source correctly refused that expired setup. Source change needs no
+schema migration and preserves old rows/idempotent timestamps exactly.
+
+## Review temporal source successor and hand off independently pinned repair
+
+```task
+id: APPROVAL-WP-0006-T02
+status: todo
+priority: high
+```
+
+Supply exact patch/test/source review evidence for coordinator integration and
+Access/Secrets immediate strict CAS remeasurement. Review only Approval facts,
+normalized preapproval correspondence and temporal bounds on the exact successor
+source. Existing WP0005 closure/R1 review remain historical; native issuer,
+audit receiver, served-PEP/CAS/effect and cleanup gates remain WP0002 T01/T04/T05
+and the existing Access/Secrets/Platform records. No native gate is closed here.

View file

@ -0,0 +1,20 @@
{
"owner": "approval-engine",
"source_revision": "3485415b823faf4f3b682079195e186666b0ed2b",
"work_item": "APPROVAL-WP-0006-T01",
"patch_sha256": "74eb0ff67d14508c2a2cee14d055790321ee171a96d5290ad6d037ce8f61dbcd",
"owner_dirty_baseline_sha256": "d076c2525b659279bddf1c56c037a77cb67bc0ad59b746cc1c377b4f1a6949e9",
"files": {
"adapters/go/approvalfact/README.md": "ac8f85d83c50a59c74a0d6ffa5f2bba9a414b2aab4e11a49c3dcc16e1b5201fc",
"approval_engine/store.py": "866b275ed2d844d0aa9090ce9899ce955c6bfe32a493c2645c86e72efa343e86",
"docs/approval-consumption.md": "31eee8a1a975bc1ad6a77ca0973208b2fc636c68cb0c748cb8aa666d5618be85",
"tests/test_timestamp_precision.py": "cbffa9265546a685b802702f5baf4e9d9ee822aaacab83c9a15c6c7316ee989b",
"workplans/APPROVAL-WP-0006-fractional-consumption-time.md": "7fe8fddb06894e87a89236eda3a3292d1d1495404b1b6a368bbfb0159d8c17ce"
},
"canonical_written": false,
"native_accepted": false,
"status": "standalone precision repair source frozen; exact Access R3 Approval fact/temporal review delivered separately",
"supplementary_owner_review_sha256": "fd5a00c498940fcfeaf188bded42de2f55b2fd04d0f78f294cc00610f5af3a6b",
"supplementary_owner_review_record_patch_sha256": "fd69252bfa12825158eb2333d4d3816a1cdde5f67b58e937dd4f8bd321627073",
"owner_review_record_applies_after": "implementation.patch"
}

View file

@ -0,0 +1,121 @@
diff --git a/.custodian-brief.md b/.custodian-brief.md
index 4e8f8d3..cbefd12 100644
--- a/.custodian-brief.md
+++ b/.custodian-brief.md
@@ -2,11 +2,17 @@
# Custodian Brief — approval-engine
**Domain:** infotech
-**Last synced:** 2026-10-11 13:46 UTC
+**Last synced:** 2026-10-16 14:28 UTC
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
## Active Workstreams
+### Approval fact contract and reusable Go data adapter
+Progress: 2/3 done | workplan_id: `777b17de-2c1e-5ce5-aa82-c99e5137e956`
+
+**Open tasks:**
+- · Independently integrate owner contract and coordinate Access reader conformance `3275354d`
+
### Production readiness and consumer adoption
Progress: 3/6 done | workplan_id: `4fa25ad5-f5d0-5592-aa59-085f8ee3edaf`
@@ -20,7 +26,7 @@ Progress: 3/6 done | workplan_id: `4fa25ad5-f5d0-5592-aa59-085f8ee3edaf`
## Inbox Hygiene
-**Stale unread:** 10 message(s) older than 3 day(s) — triage at session start.
+**Stale unread:** 11 message(s) older than 3 day(s) — triage at session start.
**Missing thread_id:** 9 unread message(s) lack supersession chains.
- ! informed-decision: INFD-WP-0005: service-requested approvals from informed-decision intake (two small asks) `59c5ee82`
- ! flex-auth: FLEX-WP-0020 handoff request (consumer) `2523510b`
diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md
index 2110857..11d89d3 100644
--- a/WORK-RECORDS.md
+++ b/WORK-RECORDS.md
@@ -10,12 +10,16 @@
| --- | --- | --- | --- | --- |
| workplan | APPROVAL-WP-ADHOC-2026-10-10 | finished | — | workplans/ADHOC-2026-10-10.md |
| workplan | APPROVAL-WP-ADHOC-2026-10-11 | finished | — | workplans/ADHOC-2026-10-11.md |
+| workplan | APPROVAL-WP-ADHOC-2026-10-16 | finished | — | workplans/ADHOC-2026-10-16.md |
| workplan | APPROVAL-WP-0001 | finished | — | workplans/APPROVAL-WP-0001-v07-alignment-and-engine-spine.md |
| workplan | APPROVAL-WP-0002 | blocked | — | workplans/APPROVAL-WP-0002-production-readiness-and-consumer-adoption.md |
| workplan | APPROVAL-WP-0003 | finished | — | workplans/APPROVAL-WP-0003-reissue-expired-approvals.md |
+| workplan | APPROVAL-WP-0004 | finished | — | workplans/APPROVAL-WP-0004-exact-consume-source-provenance.md |
+| workplan | APPROVAL-WP-0005 | active | — | workplans/APPROVAL-WP-0005-access-claim-fact-contract.md |
| task | APPROVAL-WP-ADHOC-2026-10-10-T01 | done | — | workplans/ADHOC-2026-10-10.md |
| task | APPROVAL-WP-ADHOC-2026-10-11-T01 | done | — | workplans/ADHOC-2026-10-11.md |
| task | APPROVAL-WP-ADHOC-2026-10-11-T02 | done | — | workplans/ADHOC-2026-10-11.md |
+| task | APPROVAL-WP-ADHOC-2026-10-16-T01 | done | — | workplans/ADHOC-2026-10-16.md |
| task | APPROVAL-WP-0001-T01 | done | — | workplans/APPROVAL-WP-0001-v07-alignment-and-engine-spine.md |
| task | APPROVAL-WP-0001-T02 | done | — | workplans/APPROVAL-WP-0001-v07-alignment-and-engine-spine.md |
| task | APPROVAL-WP-0001-T03 | done | — | workplans/APPROVAL-WP-0001-v07-alignment-and-engine-spine.md |
@@ -32,6 +36,11 @@
| task | APPROVAL-WP-0002-T05 | wait | — | workplans/APPROVAL-WP-0002-production-readiness-and-consumer-adoption.md |
| task | APPROVAL-WP-0002-T06 | done | — | workplans/APPROVAL-WP-0002-production-readiness-and-consumer-adoption.md |
| task | APPROVAL-WP-0003-T01 | done | — | workplans/APPROVAL-WP-0003-reissue-expired-approvals.md |
+| task | APPROVAL-WP-0004-T01 | done | — | workplans/APPROVAL-WP-0004-exact-consume-source-provenance.md |
+| task | APPROVAL-WP-0004-T02 | done | — | workplans/APPROVAL-WP-0004-exact-consume-source-provenance.md |
+| task | APPROVAL-WP-0005-T01 | done | — | workplans/APPROVAL-WP-0005-access-claim-fact-contract.md |
+| task | APPROVAL-WP-0005-T02 | todo | — | workplans/APPROVAL-WP-0005-access-claim-fact-contract.md |
+| task | APPROVAL-WP-0005-T03 | done | — | workplans/APPROVAL-WP-0005-access-claim-fact-contract.md |
| intake | APPROVAL-IN-0001 | open | blue | intakes/intakes.md |
| intake | APPROVAL-IN-0002 | closed | blue | intakes/intakes.md |
| intake | APPROVAL-IN-0003 | closed | — | intakes/intakes.md |
diff --git a/workplans/ADHOC-2026-10-16.md b/workplans/ADHOC-2026-10-16.md
index cd19170..8cda495 100644
--- a/workplans/ADHOC-2026-10-16.md
+++ b/workplans/ADHOC-2026-10-16.md
@@ -10,6 +10,7 @@ owner: codex
topic_slug: netkingdom
created: "2026-10-16"
updated: "2026-10-16"
+state_hub_workstream_id: "51585baa-f3c3-5203-9f32-3f0a3c94f889"
---
## Refuse Python-equal JSON-distinct consumed act bindings
@@ -18,6 +19,7 @@ updated: "2026-10-16"
id: APPROVAL-WP-ADHOC-2026-10-16-T01
status: done
priority: high
+state_hub_task_id: "ff45b583-a021-5a06-bb8d-3ba09674d1f8"
```
Bounded source repair demanded by the CUST-WP-0080 strict execution-seam proof.
diff --git a/workplans/APPROVAL-WP-0005-access-claim-fact-contract.md b/workplans/APPROVAL-WP-0005-access-claim-fact-contract.md
index abdb945..ba0b9af 100644
--- a/workplans/APPROVAL-WP-0005-access-claim-fact-contract.md
+++ b/workplans/APPROVAL-WP-0005-access-claim-fact-contract.md
@@ -11,6 +11,7 @@ topic_slug: netkingdom
created: "2026-10-16"
updated: "2026-10-16"
depends_on: []
+state_hub_workstream_id: "777b17de-2c1e-5ce5-aa82-c99e5137e956"
---
CUST-WP-0080 explicitly selects the necessary Approval-WP-0002-T01/T05 source
@@ -26,6 +27,7 @@ policy eligibility or live action is included.
id: APPROVAL-WP-0005-T01
status: done
priority: high
+state_hub_task_id: "24bf384a-fdd0-566d-a1d3-5e89023a7521"
```
INTENT basis: factual exact-bound approval claims supplied to Access, never a
@@ -41,6 +43,7 @@ request-refresh design requires change; fresh facts are verified out-of-band.
id: APPROVAL-WP-0005-T02
status: todo
priority: high
+state_hub_task_id: "3275354d-d781-53cf-aec6-975c0d4a601a"
```
Coordinator reviews/integrates these source records. Access owns the thin Go
@@ -56,6 +59,7 @@ is created, promoted or marked complete by these source-only fixtures.
id: APPROVAL-WP-0005-T03
status: done
priority: high
+state_hub_task_id: "362bfe75-1cd7-5081-971b-b55ce483c802"
```
Explicit bounded implementation demand after Access confirmed the exact module