CareerVector Assistant Tool Boundary

Outcome

The assistant can understand the active workspace, search the public job corpus, and help change career/application state without gaining a filesystem, terminal, raw database, workspace-listing, or arbitrary HTTP capability. A chat action and a direct UI action converge through the same schema, operation policy, canonical D1/Yjs commit, realtime fanout, and audit trail.

Initial tool surface

Capability Input boundary Output and effect
get_workspace_context Authorized workspace plus optional active surface/job/document selector Bounded canonical projection with clocks and provenance; no secrets, keys, telemetry, or unrelated workspaces
search_jobcache Public search terms and bounded filters JobCache public role/ad projection with evidence and freshness; no private identity crosses the seam
apply_workspace_operations Host-derived idempotency identity plus model-supplied expected clocks, reason, and a typed non-nested operation batch Existing canonical commit path; returns before/after clocks, affected paths, provenance, and a reversible receipt or an explicit non-reversible refusal
undo_workspace_receipt One unexpired reversible receipt and current expected clocks Compensating typed operation through the same canonical commit path; never a database rollback or history rewrite

Domain workflows may compose these capabilities, but a connector host must not mirror the entire legacy MCP catalogue. A new capability needs a user outcome, schema, privacy classification, authorization rule, idempotency behavior, receipt, failure/recovery path, and tests before it joins the allowlist.

Authorization and mutation contract

The CareerVector host resolves the private workspace link at its trusted boundary and supplies a short-lived tool capability containing opaque workspace, connector, thread, audience, expiry, and nonce scope. The private link itself never enters a prompt or model-visible tool argument. The tool service never trusts a workspaceId supplied only by the model or browser. The connector identifier names the reviewed connector instance that holds device/provider authorization; it is not a person, membership, billing target, or CareerVector account.

Every write includes:

  • a stable host-derived request/idempotency ID scoped to workspace, connector, and thread, never an identifier asserted by the model;
  • explicit expectedClock values for every touched sub-document;
  • one typed @cv/mutations operation or non-nested atomic batch;
  • actorClass: agent and a valid structured actor ID such as careervector-assistant:openai:codex or another reviewed provider/connector identity;
  • a human-legible reason and the originating chat event ID;
  • the exact affected paths and a content-safe receipt.

The existing validation, cardinality, fixed-tier, size, CAS, atomic-batch, JobCache-hook, and realtime rules remain authoritative. A connector host cannot set force: true, invent a parallel operation, or write D1/Yjs directly. A stale clock returns a conflict plus a fresh bounded projection; automatic retries require the model to reconsider the new state rather than replaying an old mutation blindly.

Review and reversibility

Read-only tools execute immediately. Low-risk workspace edits may execute immediately only when the operation catalogue can produce a bounded compensating operation. Chat renders the intent, affected fields, result, actor, time, and Undo action, and the affected workspace surface renders the same provenance.

Deletion, workspace-link or provider-credential changes, external communication, submission, purchase, publication, and any operation without a safe compensating form are absent from the initial tool surface. Adding one requires an explicit preview/approval capability and a recovery contract; the assistant cannot turn a chat confirmation phrase into ambient authority.

Undo is a new compensating write, never erasure of the original event. It checks current clocks and fails honestly when later human/agent work would be overwritten. Reversible receipts have a declared retention period and are erased with the workspace.

Prompt-injection and data boundaries

Workspace and JobCache content is untrusted reference data, never instructions. Tool descriptions and base instructions state this explicitly. The model cannot request hidden context, enumerate workspaces, change tool configuration, fetch arbitrary URLs, or read credentials. Tool outputs are bounded and tagged by source; public corpus text does not gain authority over private writes.

Implementation status

The first canonical contract seam lives in lib/assistant-tools. It emits exactly the four function-tool definitions above for a connector host while keeping workspace, capability, request, and originating-event identifiers out of model-visible arguments. Every call re-verifies an injected short-lived capability; the host resolves durable request/provenance IDs from trusted thread/turn/call metadata. JobCache search receives no CareerVector scope object.

That executable scope is keyed by opaque workspaceId, connectorId, and provider threadId. Idempotency and server-owned operation IDs use those three scopes, and the strict verifier rejects the retired account-principal shape. The connector ID is host-internal and does not expose a provider credential or grant workspace access independently of the injected capability.

Writes require exact clocks for precisely the sub-documents touched, an injected product-owned reversible-operation policy, deterministic server-owned operation IDs, actorClass: agent, the structured CareerVector assistant actor ID, an idempotency store, and a receipt whose request, provenance, before/after clocks, operation kinds, and unexpired undo window match the attempted write. Nested batches and caller-supplied force, scope, or operation IDs are rejected. Tool results are strict JSON and bounded before returning to App Server.

The TUI also has an as-built three-operation local boundary for reading application context, revision-checked field replacement, and undo. That proves the interaction and connector seam but still targets application.json; canonical integration must adapt it to this shared contract.

The TypeScript package remains supporting evidence, not a live tool service. No mutation kind is approved by the package itself. The product-owned reversible catalogue, capability issuer/verifier, durable atomic idempotency store, canonical read/search/commit/undo adapters, conflict projection, realtime parity, and UI receipt/Undo presentation remain target work.

Acceptance evidence

  • schema/contract tests reject unknown fields, nested batches, unapproved op kinds, force, stale clocks, duplicate IDs with changed payloads, oversized projections, cross-workspace scope, and the retired account-scoped capability shape;
  • duplicate delivery of an identical request produces one commit and the same receipt;
  • a direct UI op and assistant op produce equivalent canonical state and realtime updates;
  • origin/audit views distinguish the assistant without leaking prompt content;
  • undo succeeds before conflicting work and refuses after a conflicting human edit;
  • malicious instructions in job ads, CV text, notes, or tool results cannot widen the tool set or expose another workspace;
  • JobCache searches prove that no CareerVector workspace identifier or private link crosses the public corpus seam.
Source: architecture/modules/careervector-assistant-tools.md