Files
kandev/docs/plans/plugins-capability-approval/plan.md
T
2026-09-15 23:16:06 +01:00

4.1 KiB

created, status, requirements, system_design, legacy_specs
created status requirements system_design legacy_specs
2026-09-07 done
REQ-PLUGINS-CAPABILITY-APPROVAL-001
REQ-PLUGINS-CAPABILITY-APPROVAL-002
REQ-PLUGINS-CAPABILITY-APPROVAL-003
REQ-PLUGINS-CAPABILITY-APPROVAL-004
REQ-PLUGINS-CAPABILITY-APPROVAL-005
REQ-PLUGINS-CAPABILITY-APPROVAL-006
../../specs/plugins/system-design/capability-approval.md

Implementation Plan: Generic Plugin Capability Approval and Audit (H6)

Overview

Add the generic plugin capability-approval substrate as one vertical work order: host-minted installation identity, the workspace-scoped approval ledger with exact-revision admission, the append-only event trail, the fail-closed authorization decision with typed deny reasons, uninstall tombstones with reinstall identity, the legacy v1 fence, and the audit receipt primitives. Scope is the substrate only: no approval UI, no coordinator surface, and no host receipt persistence.

Scope

In scope

  • installation_id minting and persistence on the plugin store record.
  • One current CapabilityApproval per (installation_id, workspace_id).
  • Grant, narrow, revoke, and upgrade-review events in an append-only ledger.
  • Exact-revision admission and audit-id idempotency.
  • Fail-closed AuthorizeCapability with stable typed deny reasons.
  • Uninstall tombstone and reinstall identity mints.
  • The host.v2 exact-capability fence for legacy v1 declarations.
  • ApprovalReceipt and canonical digest primitives.

Out of scope

  • Approval or review UI, coordinator surfaces, dashboards.
  • Host adapter persistence of audit or read/write receipts.
  • Changes to legacy v1 runtime behavior beyond fencing it from approval authority.
  • H1-H5 plugin capabilities; this initiative is substrate only.

No UI changes

This package does not create or change rendered UI, so no ASCII UI preview is included.

Technical approach

The ledger (approvals.json under the plugins directory) owns approvals, events, tombstones, and idempotency inputs. One current approval per installation/workspace pair is stored keyed by the pair with exact next revision admission; every mutation appends an event carrying before/after revisions and digests. installation_id is minted at install time and attached to the store record; reinstall mints fresh identity and tombstones block the old identity permanently.

The authorization path (approval_service.go) is a pure decision function that evaluates in a fixed order — malformed request, human-reserved, missing approval (including the foreign-workspace alias), revoked or tombstoned, stale revision, manifest intersection, approved list — and returns a typed decision carrying the audit identity and a bounded receipt. Legacy v1 declarations keep their behavior but are fenced from approval admission and authorization.

Tests

  • approval_test.go, approval_store_test.go, approval_service_test.go: canonicalization, exact-revision admission, idempotency, tombstone, and reinstall-identity coverage.
  • approval_api_test.go, approval_query_test.go: API list/get, grant, and revoke flows including conflict semantics.
  • approval_dto_test.go: DTO shape and receipt bounds.
  • Store install/sync tests: installation_id minting and persistence.

E2E tests

No new E2E is required: the substrate exposes no UI surface. Go unit and integration tests exercise the full ledger and decision matrix; a browser duplicate of that matrix would add cost without observable UI coverage.

Work orders

Verification results

  • cd apps/backend && go build ./... passed on the H6 head and was re-verified on the merged head.
  • cd apps/backend && go test ./internal/plugins/... passed in 10 packages on the H6 head and was re-verified on the merged head.

Risks

  • Ledger file corruption must not grant authority: unknown fields decode forward-compatibly and missing maps initialize empty, but any decode failure must fail closed at lookup.
  • A future policy revision must not silently reinterpret stored approvals: the per-row human policy version is the stability point.