Skip to content

feat(model): type the plugin operation binding on Approval - #6

Closed
lr00rl wants to merge 1 commit into
mainfrom
feat/approval-operation-binding
Closed

feat(model): type the plugin operation binding on Approval#6
lr00rl wants to merge 1 commit into
mainfrom
feat/approval-operation-binding

Conversation

@lr00rl

@lr00rl lr00rl commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Adds typed columns to model.Approval for the Bundle V2 §9.3 host-risk operation binding, so the server can bind an approval to the exact code and inputs that produced its plan without stuffing them into the free-form Plan string.

What

Six additive, omitempty fields on Approval:

field purpose
plugin_version the version that produced the plan; execute rejects if the plugin has since been upgraded
artifact_digest the exact signed artifact; execute rejects if it was re-signed
service / method which plan-effect method produced this
request_sha256 the request that produced the plan — an approval can't be replayed against inputs the operator never saw
targets the full node set (NodeID stays as targets[0])

Same fields added to the ApprovalView proto message (15–20) and the proto contract test, so the wire type carries the binding and a reviewer sees which plugin version, which artifact, which nodes will actually run.

Why typed columns instead of a hashed blob

The server's first cut at §9.3 (lattice-server #12) put this tuple inside the Plan string and relied on the plan hash to bind it. That works, but it makes the binding a property of "the hash of a JSON blob" rather than of individual fields. Typed columns let each field be compared to live state directly at execute time — which is exactly what §9.3 step 3 asks for — and make the binding legible in the audit trail and the review UI.

Compatibility

Every field is omitempty and additive. An approval that is not a plugin operation (nft, dns, agent-update) serializes byte-identically to before, and NodeID is unchanged, so the existing per-node approval machinery keeps working.

Consumed by

lattice-server's §9.3 rework points its go.mod at this branch's commit and switches from the envelope-in-Plan approach to these typed fields. Re-point to the tagged SDK release before merge.

Test plan

  • go build ./... + go test ./... (model + proto contract) green

https://claude.ai/code/session_01FzYExyy6G7Cb7QpXoUEY78

Spec §9.3 binds a host-risk approval to the exact code and inputs that produced
its plan: plugin id, version, artifact digest, service, method, request hash, and
the full target set. The server had somewhere for only two of those — Plugin and a
singular NodeID — so the rest had to be smuggled into the free-form Plan string and
recovered by hashing it.

Give them real columns. Each is compared to live state at execute time and each is
what the operator's review is accountable for, so each should be a typed field, not
a value parsed back out of a blob. ApprovalView carries them too, so a reviewer sees
what will actually run — which plugin version, which artifact, which nodes.

Every field is omitempty and additive: an approval that is not a plugin operation
(nft, dns, agent update) serializes exactly as before, and NodeID stays the first
target so the per-node approval machinery is unchanged.

Tests: model build + proto contract test green.
@lr00rl

lr00rl commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

[ack] — zeus review, Olympus TASK-0001 item 4 (sdk half) (2026-07-26)

Six additive omitempty columns; proto fields 15–20 with contract test; non-plugin approvals serialize byte-identically; NodeID stays targets[0]. Evidence: this commit IS the sdk integration tip (e510bd7); gofmt/vet clean, go test -race -cover ./... ok.

Note on record: the columns were applied a second time on the sdk main line (4a318f2, sibling of the same parent) with identical definitions — main additionally carries design-15 line identity + ADR-004 stats. Integration↔main reconciliation is in front of the operator; consumers should pin sdk@4a318f2 or later. Disposition: close-with-landing-commit per rules/01 §8.5.

@lr00rl

lr00rl commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

Closed as landed — zeus, operator-approved sweep (2026-07-26, rules/01 §8.5): commit e510bd7 IS the integration tip. [ack] verdict above; integration↔main reconciliation approved and in preparation. Closing, not rejecting.

@lr00rl lr00rl closed this Jul 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant