Skip to content

refactor: mutation-default approval, tab-manager actions, DO tracking, CLA#1531

Merged
braden-w merged 14 commits intomainfrom
opencode/jolly-mountain
Mar 14, 2026
Merged

refactor: mutation-default approval, tab-manager actions, DO tracking, CLA#1531
braden-w merged 14 commits intomainfrom
opencode/jolly-mountain

Conversation

@braden-w
Copy link
Member

@braden-w braden-w commented Mar 14, 2026

Removes the per-action destructive flag and makes all mutations require approval by default. The toolTrust table (CRDT-synced [Always Allow]) already solves approval fatigue—this change flips the default so developer omission can't silently bypass approval.

The old system required destructive: true on each action. Out of 8 tab-manager mutations, only tabs.close had it—the other 7 auto-executed with zero friction. That's not a deliberate choice; it's an omission.

// BEFORE: developer must remember to opt in
close: defineMutation({
  destructive: true,  // ← forget this and mutations auto-execute
  handler: () => { ... },
}),

// AFTER: approval is automatic for all mutations
close: defineMutation({
  handler: () => { ... },  // needsApproval: true by action type
}),
BEFORE                                  AFTER
─────                                   ─────
actionsToClientTools()                  actionsToClientTools()
  for each action:                        for each action:
    if action.destructive                   if action.type === 'mutation'
      → needsApproval: true                   → needsApproval: true
    else                                    if action.type === 'query'
      → (omitted, auto-executes)              → (omitted, auto-executes)

Result:                                 Result:
  tabs.close  → approval ✓               tabs.close    → approval ✓
  tabs.open   → auto-execute ✗           tabs.open     → approval ✓
  tabs.pin    → auto-execute ✗           tabs.pin      → approval ✓
  tabs.save   → auto-execute ✗           tabs.save     → approval ✓
  tabs.dedup  → auto-execute ✗           tabs.dedup    → approval ✓
  tabs.search → auto-execute ✓           tabs.search   → auto-execute ✓

The trust escalation flow is unchanged—users click [Always Allow] once per mutation and the preference syncs across devices via CRDT.

Other changes in this branch

Tab manager: Extract shared tab helpers (findDuplicateGroups, groupByDomain) from quick-actions into tab-helpers.ts and expose tabs.dedup and tabs.groupByDomain as workspace actions. Add trust revocation settings popover in the AI drawer so users can manage their [Always Allow] grants.

API: Track Durable Object instances with storage size on every access (durable_object_instance table + migration). Add deleteStorage RPC method to BaseSyncRoom. Simplify afterResponse queue drain API.

Infrastructure: Add CLA for commercial licensing. Redesign GitHub issue templates and PR template for prose-first contributions. Add CODEOWNERS.

Docs: Writing voice financial language guideline. Git skill compression (remove redundant sections, collapse ASCII art catalog). Piggybacking storage tracking article. Multiple specs marked as implemented.

braden-w added 14 commits March 13, 2026 22:43
…yDomain as workspace actions

- Extract pure helpers (normalizeUrl, findDuplicateGroups, groupTabsByDomain) to tab-helpers.ts
- Add tabs.findDuplicates query, tabs.dedup destructive mutation, tabs.groupByDomain mutation
- Trim QuickActions from 5 to 2 (dedup + groupByDomain), remove sort/saveAll/closeByDomain
… ActionMeta

All mutations will require approval by default. The per-action
destructive flag is no longer needed.
…e flag

All mutations now get needsApproval: true. Queries omit it entirely.
The toolTrust table handles approval fatigue via [Always Allow].
…ntics

All mutations now get needsApproval, not just destructive ones.
Queries still omit it entirely.
The action type (query/mutation) now determines approval semantics.
MCP consumers can infer approval from the existing `type` field.
The destructive field no longer exists on ActionDescriptor.
tabs.close now gets approval because it's a mutation, not because of
an explicit destructive flag.
…JSDoc

Updates tool-trust, system-prompt, and chat-state comments to reflect
the new mutation-default approval model.
Missed in Phase 6 — added after the spec was written. Now removed
to match the mutation-default approval model.
Users can now view and revoke "Always Allow" tool decisions from a
gear icon in the AI chat drawer header. TrustSettings.svelte shows
trusted tools with Switch toggles and a "Revoke All" option.

Spec: specs/20260314T061500-tool-trust-revocation-settings.md
Check off all implementation items and success criteria, add review
section noting the extra tabs.dedup call site discovered during
implementation.
@braden-w braden-w changed the title docs(specs): mark progressive tool trust spec as implemented refactor: mutation-default approval, tab-manager actions, DO tracking, CLA Mar 14, 2026
@braden-w braden-w merged commit 395acc7 into main Mar 14, 2026
1 of 9 checks passed
@braden-w braden-w deleted the opencode/jolly-mountain branch March 14, 2026 09:53
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