Bind the budget memo and point sitting admission at compact-sitting v2

attach_compact_bindings takes --sitting/--batches (defaults unchanged).
b01 is bound to the existing named recipient and native approval
ba5ce2d8. sitting-admission.json moves to package v2
(sha256:24a52478...) and the currently served image ef6fdd61, so the
cutover does not roll back the 2026-09-16 login fixes. Not yet applied.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 272244@bnt-lap001
Assistant-Session: c8962fa7-b290-47df-865f-403ddb6c77e9
This commit is contained in:
tegwick 2026-09-21 21:34:55 +02:00
parent e99fb5892a
commit 6d0a81f728
5 changed files with 78 additions and 6 deletions

View file

@ -1,10 +1,10 @@
{
"image": "forgejo.coulomb.social/coulomb/informed-decision@sha256:8f55bcecf37a8d65f96e073510b1ffb4636c0a91d75e1ee7d582ad4bce8b953a",
"image": "forgejo.coulomb.social/coulomb/informed-decision@sha256:ef6fdd61209863654be3adba070661645a2714e86cb4b7f4e847540291b55f07",
"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",
"version": "v2",
"package_digest": "sha256:24a524785740e60df70e0ced4d884f1a6197bf3fbf7b003471947ce76b763ead",
"pod_name": "flex-auth-informed-decision-sitting"
},
"keycape_egress_ips": [

View file

@ -0,0 +1,15 @@
{
"kind": "informed-decision-bound-sitting",
"sitting_id": "infd-sitting-2026-09-21",
"principal": "uid=platform-root,ou=people,dc=netkingdom,dc=local",
"submitted": false,
"agent_disposition_forbidden": true,
"memos": [
{
"memo_id": "infd-20260921-b01",
"approval_id": "ba5ce2d8-8b6d-40be-af89-2e8c147029a3",
"memo": "infd-20260921-b01.memo.json",
"packet": "infd-20260921-b01.packet.md"
}
]
}

View file

@ -0,0 +1 @@
{"approval_binding_digest":"sha256:e9eaf454e94871ec2060855fcfbd327bcaec873d2c61cae031bec9f95a34bcae","approval_id":"ba5ce2d8-8b6d-40be-af89-2e8c147029a3","binding":{"justification":null,"principal":{"display_name":"uid=platform-root,ou=people,dc=netkingdom,dc=local","id":"uid=platform-root,ou=people,dc=netkingdom,dc=local","identifiers":[],"kind":"person","role":"reviewer"},"target":{"environment":"prod","id":"spend-envelope:hfact-glas-anthropic-2026-09","kind":"spend-envelope","label":"Glas metered runs on the Anthropic key (railiance01)","requires_new_bind":false},"terms":null},"binding_level":"organizational","brief":"Sets the spending authority that rein-aharness MessagesOwner enforces before each metered Glas run on railiance01. Accepting it does not deliver the key, run a model or create an OpenBao policy; those are three separate SECRETS-WP-0009-T03 approvals. The EUR 100 monthly limit is recorded here but not enforced by the software.","highlights":[{"id":"infd-20260921-b01-h1","item_id":"infd-20260921-b01-packet","locator":{"kind":"work_record","task":"SECRETS-WP-0009-T03","workplan":"SECRETS-WP-0009"},"note":"The EUR 100 per month limit is NOT enforced: SpendPolicy has no monthly ceiling. Only EUR 5 per run, EUR 20 per day and EUR 500 total are enforced. Every completed run is charged its full reservation (EUR 4.9938), not its actual cost.","required_ack":true,"severity":"critical"}],"id":"infd-20260921-b01","locale":"en","packet":[{"hash":"sha256:a3d3f4e33d75579795c0e407971c0d472432569ef68a9408e9897587a58f0deb","item_id":"infd-20260921-b01-packet","label":"infd-20260921-b01-packet"}],"question":"Accept the spend envelope for metered Glas runs on the Anthropic key (EUR 5 per run, 20 per day, 500 total, until 2027-01-31)?","requested_act":"approve","sealed":false,"step_kind":"approve","ui_release":"informed-decision@0.2.0","version":1}

View file

@ -0,0 +1,51 @@
# SECRETS-WP-0009-T03 — spend envelope for metered Glas runs
Blocking workplan: SECRETS-WP-0009
Blocking task: SECRETS-WP-0009-T03 (hub prefix f8069c8a)
Related: HFACT-WP-0001-T01/T04 (SpendPolicy and owner config), GLAS-WP-0012
## Question
Accept the spend envelope for metered Glas runs on the Anthropic key (EUR 5 per run, 20 per day, 500 total, until 2027-01-31)?
## One act
Accept this envelope as the spend authority for rein-aharness MessagesOwner
`metered-once` runs on railiance01 using the Anthropic key of catalog lane
`glas-claude-agent-dev-anthropic`. The accepted approval id becomes the
SpendPolicy `authority_ref` for envelope `hfact-glas-anthropic-2026-09`.
## Enforced values (rein-aharness SpendPolicy, decimal strings)
| Field | Value | Note |
| --- | --- | --- |
| `per_run_eur` | 5 | Operator-stated |
| `daily_eur` | 20 | Operator-stated; timezone Europe/Berlin |
| `total_eur` | 500 | Operator-stated; over the whole envelope |
| `eur_per_usd` | 0.87 | Operator rate 1 EUR = 1.15 USD (1/1.15 = 0.8696), rounded up |
| `max_liability_usd` | 5.74 | Per run. Reserves ceil(5.74 x 0.87) = EUR 4.9938, inside EUR 5 |
| `max_budget_usd` | 5.00 | Per run. Claude CLI stop threshold, inside liability |
| `valid_from` | acceptance time | |
| `expires_at` | 2027-01-31T23:59:59+01:00 | Operator-stated |
Resulting capacity: at most 4 runs per day and 100 runs in total. A completed run
is charged its full reservation, not its reported cost. A failed, cancelled or
unaccounted run keeps its reservation and blocks further runs until reconciled.
Cost above liability permanently marks the envelope breached.
The operator's overall USD 600 budget and USD 800 liability caps are dominated
by `total_eur` 500 (= USD 575) and need no separate field.
## Recorded, not enforced
- EUR 100 per calendar month. SpendPolicy has no monthly ceiling; a rein-aharness
follow-up adds `monthly_eur`. Until then the operator reviews monthly use.
## Scope bound by the SpendPolicy, filled in before the private file is written
`worker_id`, `activity_definition_id`, `target_repo`, `project`, `profile_ref`,
`profile_sha256`, `descriptor_sha256`, `repository_grant_id`, `max_turns` come from
the admitted factory profile (HFACT-WP-0001-T01). They narrow this envelope; they
cannot widen the amounts above.
## Must not
- Deliver, read or display the Anthropic key
- Authorize the OpenBao apply, verify or exec actions (separate T03 approvals)
- Cover llm-connect or its DeepSeek default; that path is not this envelope
- Raise any amount or extend the expiry without a new memo

View file

@ -45,13 +45,13 @@ def _approval(row: dict, memo_id: str) -> dict:
return approval
def attach(principal: str, receipt: dict, root: Path = ROOT) -> dict:
def attach(principal: str, receipt: dict, root: Path = ROOT, batches: tuple[str, ...] = ("credentials", "decisions")) -> dict:
actor = _principal(principal)
if receipt.get("status") != "created":
raise ValueError("created native receipt required")
sitting = json.loads((root / "sitting.json").read_text())
expected = []
for name in ("credentials", "decisions"):
for name in batches:
index = json.loads((root / name / "index.json").read_text())
for row in index["ordinal"]:
expected.append((name, row["memo_id"], row["memo"], row["packet"]))
@ -108,9 +108,14 @@ def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--principal", required=True, help="exact live KeyCape subject")
parser.add_argument("--receipt", type=Path, required=True, help="native created-approval receipt")
parser.add_argument("--sitting", help="batch date directory under docs/batches; default 2026-09-14")
parser.add_argument("--batches", default="credentials,decisions", help="comma-separated batch directories")
args = parser.parse_args()
receipt = json.loads(args.receipt.read_text())
index = attach(args.principal, receipt)
root = ROOT.parent / args.sitting if args.sitting else ROOT
if args.sitting and "/" in args.sitting:
raise SystemExit("sitting must be a directory name")
index = attach(args.principal, receipt, root, tuple(b for b in args.batches.split(",") if b))
print(json.dumps({"status": "bound_copies_written", "count": len(index["memos"])}, indent=2))
print("No presentations, dispositions, or approval entries created.")