Cut review over to the sitting PDP and load seven memos.

FLEX-WP-0028 admitted a dedicated package. Runtime ConfigMap and
NetworkPolicy now pin flex-auth-informed-decision-sitting. Memos are
in the live store for the existing named recipient. No human bind.

Assistant: grok
Assistant-Session: 01a09dc1-b21e-77e1-919e-fcad2f82b267
This commit is contained in:
tegwick 2026-09-15 23:35:35 +02:00
parent ca563504c4
commit d4b77a8c0e
6 changed files with 115 additions and 15 deletions

View file

@ -0,0 +1,14 @@
{
"image": "forgejo.coulomb.social/coulomb/informed-decision@sha256:8f55bcecf37a8d65f96e073510b1ffb4636c0a91d75e1ee7d582ad4bce8b953a",
"policy": {
"origin": "http://flex-auth-informed-decision-sitting.flex-auth.svc.cluster.local:8080",
"package": "informed-decision.compact-sitting",
"version": "v1",
"package_digest": "sha256:e0afd52e046616a93142f4064704b1cee6496801d94612fce29a958cf04eb41a",
"pod_name": "flex-auth-informed-decision-sitting"
},
"keycape_egress_ips": [
"92.205.62.239"
],
"storage_class": "local-path"
}

View file

@ -83,8 +83,20 @@ Open in this order. One question each. No approve-all.
writes `bound/` copies. Unsigned drafts stay unsigned.
4. Flex Auth admits a **new** package pinning those eight `memo:` ids to the
native approval id/digest, same identity bar as T03, deny everything else.
5. Load packet bytes then `save_memo` from `bound/` into the review store.
6. Sign in. Open `/review?memo_id=infd-20260914-c01` through `…-d04` in order.
5. 2026-09-15 21:31 UTC: review runtime now uses sitting PDP
`flex-auth-informed-decision-sitting` / `informed-decision.compact-sitting`.
Seven memos are in the live store for the existing named recipient. `c01`
is not loaded.
6. Sign in at https://decisions.coulomb.social/ . Open in order:
`/review?memo_id=infd-20260914-c02`
`/review?memo_id=infd-20260914-c03`
`/review?memo_id=infd-20260914-c04`
`/review?memo_id=infd-20260914-d01`
`/review?memo_id=infd-20260914-d02`
`/review?memo_id=infd-20260914-d03`
`/review?memo_id=infd-20260914-d04`
Acknowledge the required highlight. Bind that memo. Repeat.
7. Unfinished memos stay in the batch. File-level owning-repo updates are T04
after a human bind, via `fix-consistency`, never `POST /workplans/`.

View file

@ -51,21 +51,33 @@ def test_attach_writes_bound_copies_and_leaves_drafts_unsigned(tmp_path):
(root / "sitting.json").write_bytes((src / "sitting.json").read_bytes())
ids = _memo_ids(root)
index = attach_mod.attach("human-subject-1", _receipt(ids), root)
assert index["principal"] == "human-subject-1"
assert len(index["memos"]) == 8
draft = memo_from(json.loads((root / "credentials" / "infd-20260914-c01.memo.json").read_text()))
def test_attach_allows_seven_memo_subset(tmp_path):
src = Path(__file__).resolve().parents[1] / "docs" / "batches" / "2026-09-14"
root = tmp_path / "sitting"
for name in ("credentials", "decisions"):
(root / name).mkdir(parents=True)
for item in (src / name).iterdir():
(root / name / item.name).write_bytes(item.read_bytes())
(root / "sitting.json").write_bytes((src / "sitting.json").read_bytes())
ids = [i for i in _memo_ids(root) if i != "infd-20260914-c01"]
index = attach_mod.attach("human-subject-1", _receipt(ids), root)
assert index["principal"] == "human-subject-1"
assert len(index["memos"]) == 7
assert "infd-20260914-c01" not in {row["memo_id"] for row in index["memos"]}
draft = memo_from(json.loads((root / "credentials" / "infd-20260914-c02.memo.json").read_text()))
assert draft.approval_id is None
assert draft.binding.principal.id == "pending-human-session"
bound = memo_from(json.loads((root / "bound" / "infd-20260914-c01.memo.json").read_text()))
bound = memo_from(json.loads((root / "bound" / "infd-20260914-c02.memo.json").read_text()))
assert bound.approval_id == "approval-01"
assert bound.approval_binding_digest.startswith("sha256:")
assert bound.binding.principal.id == "human-subject-1"
assert bound.question == draft.question
assert not (root / "bound" / "infd-20260914-c01.memo.json").exists()
@pytest.mark.parametrize(
"fault",
["pending-human-session", "has space", "", "not-created", "wrong-count", "has-entry", "no-control"],
["pending-human-session", "has space", "", "not-created", "unknown-memo", "has-entry", "no-control"],
)
def test_attach_refuses_unsafe_inputs(tmp_path, fault):
src = Path(__file__).resolve().parents[1] / "docs" / "batches" / "2026-09-14"
@ -86,8 +98,8 @@ def test_attach_refuses_unsafe_inputs(tmp_path, fault):
principal = ""
elif fault == "not-created":
receipt["status"] = "draft"
elif fault == "wrong-count":
receipt["requests"] = receipt["requests"][:7]
elif fault == "unknown-memo":
receipt["requests"][0]["memo_id"] = "not-a-sitting-memo"
elif fault == "has-entry":
receipt = _receipt(ids, entries=[{"subject_id": "someone"}])
elif fault == "no-control":

View file

@ -56,13 +56,14 @@ def attach(principal: str, receipt: dict, root: Path = ROOT) -> dict:
for row in index["ordinal"]:
expected.append((name, row["memo_id"], row["memo"], row["packet"]))
requests = receipt.get("requests") or []
if len(requests) != len(expected):
raise ValueError("receipt must cover every sitting memo once")
by_id = {row.get("memo_id"): row for row in requests}
if set(by_id) != {memo_id for _, memo_id, _, _ in expected}:
raise ValueError("receipt memo set must match the sitting")
sitting_ids = {memo_id for _, memo_id, _, _ in expected}
if not by_id or set(by_id) - sitting_ids:
raise ValueError("receipt memo set must be a non-empty subset of the sitting")
prepared = []
for name, memo_id, memo_name, packet_name in expected:
if memo_id not in by_id:
continue
approval = _approval(by_id[memo_id], memo_id)
memo = memo_from(json.loads((root / name / memo_name).read_text()))
if memo.approval_id is not None or memo.binding.principal.id != "pending-human-session":

View file

@ -0,0 +1,51 @@
"""Load bound sitting memos into a review store. Does not present or bind."""
from __future__ import annotations
import argparse
import json
from pathlib import Path
from informed_decision.records import memo_from as _memo_from
from informed_decision.store import Store
def principal_from_store(store: Store) -> str:
with store._connection() as db:
rows = list(db.execute("SELECT body FROM presentations"))
subs = {json.loads(body)["principal_sub"] for (body,) in rows}
if len(subs) != 1:
raise ValueError("single live recipient required")
value = next(iter(subs))
if not value or value == "pending-human-session":
raise ValueError("live key-cape subject required")
return value
def load(store: Store, bound: Path) -> dict:
index = json.loads((bound / "index.json").read_text())
if index.get("agent_disposition_forbidden") is not True:
raise ValueError("bound sitting index required")
loaded = []
for row in index["memos"]:
memo = _memo_from(json.loads((bound / row["memo"]).read_text()))
packet = (bound / row["packet"]).read_bytes()
digest = store.put_document(packet)
if digest != memo.packet[0].hash:
raise ValueError(f"packet digest mismatch for {memo.id}")
store.save_memo(memo)
loaded.append(memo.id)
return {"status": "loaded", "count": len(loaded), "memo_ids": loaded}
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--db", type=Path, required=True)
parser.add_argument("--bound", type=Path, required=True)
args = parser.parse_args()
store = Store(args.db)
print(json.dumps(load(store, args.bound), indent=2))
print("No presentations or dispositions created.")
if __name__ == "__main__":
main()

View file

@ -174,6 +174,16 @@ Flex Auth draft `docs/batches/2026-09-14/policy-package.md` is not
admitted. Attach still needs the operator KeyCape `sub`. No human bind.
Task stays `wait`.
2026-09-15 21:31 UTC — **sitting PDP live on the origin; seven memos
loaded.** FLEX-WP-0028 admitted
`flex-auth-informed-decision-sitting` /
`informed-decision.compact-sitting`
(`sha256:e0afd52e046616a93142f4064704b1cee6496801d94612fce29a958cf04eb41a`).
Review ConfigMap `informed-decision-runtime-bab38e8704a2`; egress peer
cut over from T03. Named recipient reused from existing presentations
(not written to git). Store has seven `infd-20260914-*` memos plus the
three T03 records. Human bind remaining. Task stays `wait`.
## Feed outcomes back to State Hub without hub-authoring
```task