Skip to content

feat(cave): add the privileged authority tier behind capability gates - #7

Closed
CompleteDotTech wants to merge 1 commit into
feat/conversational-control-42from
feat/rich-actions-43
Closed

feat(cave): add the privileged authority tier behind capability gates#7
CompleteDotTech wants to merge 1 commit into
feat/conversational-control-42from
feat/rich-actions-43

Conversation

@CompleteDotTech

Copy link
Copy Markdown
Owner

Summary

Implements the SDK-owned half of OpenCoven#43 (rich content, attachments, and explicitly confirmed privileged actions) as far as the authoritative Cave contract allows, stacked directly on PR #6 (feat/conversational-control-42 @ 927996d). Cave remains the sole executor and canonical owner for storage, grants, confirmation, idempotency, audit, and domain mutation.

Assignee: @CompleteDotTech
Advances OpenCoven#43 (maintainer close on merge)
Dependency-graph override by user directive (2026-08-30): started despite Blocked by: #42 — stacked on PR #6; merges only after #1#5#6.

Upstream PR (one click for a maintainer): https://github.com/OpenCoven/sdk/compare/main...CompleteDotTech:sdk:feat/rich-actions-43?expand=1

Fixture audit (what the contract actually declares)

The pinned Cave Client v1 fixture (producer commit 4adc97b1, digest b2694cd1…) declares 13 operations — health, pairing (public/admin), credential admin, familiars/projects/conversations/messages reads — every authenticated one GET + chat:read. It declares no attachment, rich-content, attention, task-handoff, or GitHub operations and no such capability families. It does declare the pairing scopes chat:write, conversations:write, attachments:write, tasks:write, github:write, so the scope vocabulary is contract-real even though no operation uses it yet. Nothing in this PR invents routes, scopes, capability families, or GitHub action kinds.

What ships

  • Capability registry tied to live operations (createCaveCapabilityRegistry): resolves each privileged action class against the consulted contract's operation table per call, returning fresh frozen descriptors (no cached capability objects). The default snapshot mirrors the pinned fixture and is test-locked to its exact operation table, so a fixture re-import forces a reviewed update. Under the pinned contract every privileged class resolves undeclared.
  • Bounded attachment transfer, validation half: fail-closed file count (<=10), file size (<=10 MiB), request size (<=25 MiB), MIME allowlist with magic-byte signature agreement (spoofed declarations rejected), filename rules (no separators/dot segments/control chars/hidden dotfiles), symlink refusal, and the atomic uploader-credential-plus-conversation binding. Records are metadata-only — attachment bytes never enter canonical conversation JSON, browser storage, profile config, or diagnostic bundles; the canonical byte digest stays Cave's.
  • Passive rich content (fully implementable, no routes needed): a strict non-executable AST over a closed node vocabulary. No HTML node type, no event-handler fields, markup-looking text preserved inertly byte for byte, link targets restricted to https:/mailto: (scheme-less targets rejected, userinfo refused), node-count/depth/character limits fail closed. Hostile fixtures (script injection, event handlers, javascript:/data:/file: URLs, oversized, over-deep) all rejected or proven inert.
  • Attention responses + task handoffs: closed response kinds (acknowledge/decline) with bounded notes; handoff transitions keeping proposed/pending/completed/rejected/failed strictly distinct behind a declared transition map with terminal states.
  • Confirmed GitHub action envelope: exact confirmed: true, operation-UUID idempotency, bounded string input — with the curated action union deliberately empty (readonly never[]), so no request is even constructible: fail closed by construction until the upstream contract curates kinds.
  • Client + transport surface: five CaveClient methods (uploadAttachment, downloadAttachment, respondToAttention, requestTaskHandoff, submitGitHubAction) that validate first, then resolve the capability gate, then dispatch — reporting unsupported_operation with zero transport calls under the pinned contract; the operation UUID is attached to every privileged client error. Five matching optional unbound CaveTransport methods follow the PR feat(cave): add conversational control surface for the mutation authority #6 pattern.

Validation

  • Local corepack pnpm@10.34.0 verify (typecheck, tests, contracts, package, release, coverage, stress, lint) exit 0 on the pushed head 26aead4; git diff --check clean. 64 test files / 1,321 tests pass (42 new).
  • New suites: capability gating against the real fixture, attachment fail-closed matrix + zero-domain-call assertions, rich-content hostile fixtures, handoff/attention state distinctness, confirmation-bypass probes, synthetic declared-capability flow proving the gate is registry-driven.

Deliberately not implemented (and why)

  • No transport bindings or route paths — no operation exists for any privileged class; every binding would be a speculative route.
  • No CLI commands — the work plan requires deterministic CLI commands for explicitly supported actions only; zero privileged actions are supported end-to-end, so zero commands ship.
  • No concrete GitHub action kinds — naming any kind would fabricate a curation no producer contract has reviewed.
  • No SDK-side digest hashing — Cave computes canonical byte digests server-side where the bytes land; the SDK validates the record digest as a string only. (This also keeps the managed browser bundle free of Node built-ins.)

Owed upstream (who owes what — none of it invented here)

  1. Cave producer (OpenCoven/coven-cave): declare the attachment, rich-content, attention, task-handoff, and GitHub operations with their scope mappings and capability families; ship the attachment storage/ownership semantics, rich-content payload contract, attention/task state ownership, the curated GitHub action union, and conformance vectors for every mutation class.
  2. This SDK (after pnpm sync:contracts re-imports the new fixture): bind the five transport methods, wire the CLI commands, and extend the registry snapshot — reviewed against the landed contract.
  3. Security review: the privileged authority tier requires its own dedicated review (F-[SDK 0.1.0][P0] Complete the first-release security review and ship/block disposition OpenCoven/sdk#40-style follow-up) before any privileged class becomes actionable — scope: capability-gate ordering, confirmation + idempotency enforcement, attachment boundary/ownership rules, rich-content inertness, redaction of human/JSON output.
  4. Chat native commands: separate cross-repo debt, unchanged from the [SDK post-0.1] Ship conversational control: create, send, stream, stop, retry, reconcile OpenCoven/sdk#42 handoff.

Release implications

Changeset .changeset/rich-actions-43.md targets the release after 0.1.0 (minor on @opencoven/cave-client). API baselines regenerated (api-baselines/cave.d.ts, cave.json); public-contract export pin extended. The surface is additive and fail closed: with no Cave supporting these operations, behavior today is unsupported_operation plus the pure validation/AST layer.

Stack / merge order

#1 (security review) → #5 (0.1.0 unlock prep) → #6 (conversational control, this PR's base) → this PR. Merges only after all three land.

Implement the SDK-owned half of issue OpenCoven#43 as far as the authoritative Cave
contract allows, stacked on the conversational-control tier:

- a capability registry derived from the verified contract fixture that
  resolves every privileged action class (attachment-transfer, rich-content,
  attention-response, task-handoff, github-action) against the live operation
  table per call - frozen descriptors, no cached capability objects; the
  default snapshot mirrors the pinned fixture and is test-locked to it;
- bounded attachment transfer validated fail closed (file count, file size,
  request size, MIME allowlist with magic-byte signature agreement,
  filename, traversal, symlink) with the atomic uploader-credential-plus-
  conversation binding and metadata-only records, so attachment bytes never
  enter canonical conversation JSON, browser storage, profile config, or
  diagnostic bundles; the canonical byte digest stays Cave's;
- a passive rich-content AST over a closed non-executable node vocabulary:
  no HTML node type, no event-handler fields, markup-looking text preserved
  inertly byte for byte, link targets restricted to https:/mailto: with
  userinfo refused, node-count, depth, and character limits failing closed;
- task handoffs with proposed/pending/completed/rejected/failed kept
  strictly distinct behind a declared transition map, and attention
  responses over a closed kind union with a bounded note;
- the confirmed GitHub action envelope with an intentionally EMPTY curated
  union typed readonly never[], so no request is constructible - fail
  closed by construction - with confirmation, operation-UUID idempotency,
  and bounded-input validation shipping ready for the curated union;
- five optional unbound CaveTransport methods and five CaveClient methods
  that validate requests, resolve the capability gate, and report
  unsupported_operation with zero transport dispatch under the pinned
  contract; the operation UUID is attached to every privileged client
  error.

Upstream-contract gap (stated, not invented): the fixture pinned at Cave
4adc97b1 declares the privileged pairing scopes but no attachment,
rich-content, attention, task, or GitHub operations and no such capability
families, so no route, scope mapping, capability family, or GitHub action
kind ships; no CLI command ships for unsupported privileged actions.
Changeset targets the release after 0.1.0.
@CompleteDotTech

Copy link
Copy Markdown
Owner Author

Recreated upstream as OpenCoven#82: OpenCoven#82. Closing this duplicate fork PR; review continues upstream.

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