Interfaces

One operation. Every surface. The same policy.

Adapters are outer layers. A capability granted to a browser tool is the capability the CLI and an MCP client invoke. None of them can infer authority from the presence of a route, a tool description, or a document.

01 — Capability model

A capability is a contract, not an endpoint.

Every operation declares an ID, input and output schemas, a risk class, a required scope, expected side effects, and possible errors. The registry, not the route table, is the source of truth for what an actor may do.

RiskExamplesDefault
readworkspace.list, object.get, search.query, graph.neighborsAllowed within scope
derivecontext.bundle, snapshot.verify, index.statusAllowed; bounded resources
proposechange.preview, task.start, homepage.previewCreates a reviewable proposal
mutatechange.apply, homepage.publish, backup.createExplicit approval + version precondition
admintoken.issue, policy.grant, workspace.removeSeparate elevation; never delegated to a model

02 — REST

/api/v1, logical IDs, typed errors.

Resource paths use object and workspace IDs, never absolute paths. Writes carry idempotency keys and revision preconditions. Errors are problem details, not stack traces.

Method & pathPurpose
GET /healthDaemon, catalog, watcher, extract state
GET /api/v1/workspacesList registered workspaces
POST /api/v1/workspacesRegister a directory
GET /api/v1/objects/{id}Object metadata and provenance
GET /api/v1/objects/{id}/contentAuthorized content range
GET /api/v1/searchPermission-filtered full-text search
POST /api/v1/context/bundlesBudgeted context assembly
POST /api/v1/graph/queryBounded typed traversal
POST /api/v1/changes/previewThree-way diff, no write
POST /api/v1/changes/applyApproved, versioned write
POST /api/v1/tasks, GET /{id}Durable async work
GET /api/v1/auditLedger entries and receipts
httpsearch
GET /api/v1/search?query=architecture
    &workspace_id=wks_01JEX
Accept: application/json

200 OK
{
  "results": [
    {
      "object_id": "obj_01J9F2",
      "version": "sha256:8b708e…",
      "title": "workspace-architecture.md",
      "score": 0.82,
      "freshness": "indexed 12s ago",
      "provenance": "observed"
    }
  ],
  "next_cursor": null
}
Error shape. code, message, request_id, optional field_errors, retry_after, conflict_version, approval_request_id. A 403 never reveals the existence of a hidden object.

03 — MCP

Narrow tools for agents that must ask.

Tool annotations are hints; the server enforces. Discovery shapes are separated from execution, and a destructive tool normally returns a preview or an approval request rather than acting.

ToolRisk
intralock_workspace_listread
intralock_workspace_inspectread
intralock_object_getread
intralock_object_readread
intralock_searchread
intralock_graph_queryread
intralock_context_bundlederive
intralock_change_previewpropose
intralock_change_applymutate · approval
intralock_task_startderive · durable
intralock_snapshot_verifyread
intralock_capability_listread

Resources use intralock://workspace/{id}/…. A URI is a locator, not a bearer credential.

jsontools/call
{
  "name": "intralock_search",
  "arguments": {
    "workspace_id": "wks_01JEX",
    "query": "vendor renewal",
    "limit": 5
  }
}

→ typed results, each with
  object_id, version, freshness,
  provenance, source_url

04 — CLI

Useful on its own, scriptable by design.

Human output on stderr, machine output on stdout. JSON is schema-versioned and free of ANSI sequences. Exit codes distinguish input error, policy denial, conflict, unavailable daemon, partial completion, and internal fault.

shdaily operations
# attach and inspect
intralock init --workspace . --read-only
intralock workspaces list
intralock workspace inspect wks_01JEX

# index and search
intralock index run --workspace wks_01JEX --dry-run
intralock index status --workspace wks_01JEX
intralock search "architecture" --workspace wks_01JEX --json

# relationships and context
intralock graph neighbors obj_01J9F2 --depth 2
intralock context bundle --workspace wks_01JEX \
  --mode engineering --max-tokens 6000

# governance and evidence
intralock policies explain --actor agt_7f \
  --action read_content --object obj_01J9F2
intralock snapshot create --workspace wks_01JEX
intralock snapshot verify --workspace wks_01JEX
intralock doctor --full

Global flags

  • --workspace, --profile, --format
  • --json, --quiet, --verbose
  • --timeout, --request-id
  • --dry-run, --expected-version
  • --yes only where safe — never to bypass approval

Exit codes

  • 0 success · 2 input error
  • 3 policy denial · 4 conflict
  • 5 daemon unavailable · 6 partial completion
  • 1 internal fault

05 — GraphQL

Exploration with a budget.

Read-only query types for workspaces, objects, versions, edges, evidence, tasks, capabilities, and snapshots. Mutations route through the same preview and approval services as REST — never direct writes to graph edges.

graphqlquery
query WorkspaceOverview($id: ID!) {
  workspace(id: $id) {
    name
    freshness
    objects(first: 10, type: DOCUMENT) {
      edges { node { id title version } }
    }
    capabilities { id risk }
  }
}

Depth, field cost, result cardinality, and time budgets are enforced. Introspection is limited outside authorized development contexts. A partially unauthorized relationship is omitted, with bounded redaction metadata — never a hidden name, count, or snippet in an error.

Data loaders batch reads without losing per-object checks. Subscriptions authorize at connection and again at delivery.

06 — WebMCP & async

Browser tools, same server checks.

A browser page registers only context-relevant capabilities. Every call hits the same authenticated HTTP endpoint as the human action, with origin checks and session policy. No tokens or filesystem secrets in page JavaScript.

javascriptfeature-detected
// Illustrative: follow the tested draft's signature.
if (document.modelContext?.registerTool) {
  document.modelContext.registerTool({
    name: "search_current_workspace",
    description: "Search the open workspace only.",
    inputSchema: { type: "object",
      properties: { query: { type: "string" } } },
    execute: ({ query }) =>
      fetch("/api/v1/search", { method: "POST", … })
  });
}

Long-running work

Index refresh, large export, graph rebuild, and approved work orders return a durable task ID. Task metadata binds actor, scope, idempotency key, expiry, progress, and outcome digest. Polling is rate-limited; cancellation is re-authorized.

Events travel over bounded SSE or webhooks, authorized at subscribe time and again at delivery. A task ID is never sufficient authorization on its own.