VaultPerch
Invitation-only pilot

Fixed R2 courier onboarding

Use CLI 0.1.1 for the fixed R2 courier action through the scoped API/CLI. Start with a synthetic object and a dedicated Object Read credential.

The standalone courier action checks one object's existence and size using an owned S3 credential. VaultPerch constructs one R2 S3 HEAD request for the immutable owner-enrolled resource. It returns found with a byte count or not_found, plus safe operation metadata. It does not return an object body, credential values, ETags, provider headers or provider request IDs. The provider remains a trust boundary for the result and numeric size.

Start with the installation and invitation guide. Install the offered CLI 0.1.1 archive and verify its checksum before using the commands. Begin with a synthetic object and a dedicated credential.

1. Prepare owner custody and a protected S3 input

Accept your invitation, verify email, and create a vault and workload principal in the app. Obtain a separate R2 Object Read S3 credential restricted to the intended bucket. Do not import a deployment OAuth token, account API token or another product's credentials. Provider-side bucket scope and VaultPerch's prefix restriction are separate boundaries; VaultPerch does not create or rotate provider credentials.

Use an owner macOS Keychain profile distinct from the receiver's machine profile. Owner login/import/resource administration require owner custody; API/CLI invocation requires enrolled machine custody. Password prompts read from the terminal. Never put passwords, access keys, secret keys or tokens in command arguments, chat, source or logs.

Prepare the credential JSON through a trusted protected channel, not a shell command containing its values. The file must be a regular file owned by the current OS user, readable only by that user (normally mode 0600), with one hard link and no symlink. Keep it in a private directory. The JSON has exactly the string fields accessKeyId, secretAccessKey, and optionally sessionToken, with nonempty values and no extra fields; the input limit is 64 KiB. Do not print the file to inspect it.

In all examples, replace metadata placeholders with your account's IDs. IMPORT_OPERATION_UUIDV7, BIND_OPERATION_UUIDV7, HEAD_OPERATION_UUIDV7 and REVOKE_OPERATION_UUIDV7 mean distinct, explicit lowercase UUIDv7 values chosen and retained by you before each intended command. Do not substitute UUIDv4. Keep the original ID and non-secret intent for reconciliation.

vaultperch login --origin https://api.vaultperch.com \
  --keychain-profile courier-owner --email OWNER_EMAIL
vaultperch import --origin https://api.vaultperch.com \
  --keychain-profile courier-owner --schema s3 --vault VAULT_UUID \
  --label courier-read --file /private/location/r2-read.json \
  --operation-id IMPORT_OPERATION_UUIDV7

The import returns credential metadata and a receipt, not the key values. Use the returned owned CREDENTIAL_UUID; shared credential references are outside this profile.

2. Bind the exact resource as the owner

Recently confirm the owner password, then enroll the resource:

vaultperch reauthenticate --origin https://api.vaultperch.com \
  --keychain-profile courier-owner
vaultperch courier-enroll --origin https://api.vaultperch.com \
  --keychain-profile courier-owner --credential CREDENTIAL_UUID \
  --r2-account R2_ACCOUNT_ID --bucket courier-example --prefix readiness/ \
  --operation-id BIND_OPERATION_UUIDV7
vaultperch courier-resources --origin https://api.vaultperch.com \
  --keychain-profile courier-owner

Copy the returned RESOURCE_UUID. The immutable binding pins the owned credential's current version and vault to one global R2 account, bucket and nonempty prefix. A credential version change requires a fresh owner binding; it does not silently update the resource. Resource listing, enrollment and revocation are owner-only. Sensitive writes require password confirmation within five minutes; reauthenticate if requested.

The accepted canonical profile is:

The caller cannot supply a URL, method, headers, request body or signing options. The broker constructs the destination internally and does not follow redirects.

3. Grant and enroll the receiver separately

In the app, grant the workload principal broker:invoke on the owned credential's vault with an appropriate expiry. Metadata, import and runtime-receive grants do not imply this permission. Select the explicitly unchecked broker invocation permission in the grant form.

On the receiving Mac, use its own Keychain profile without owner login:

vaultperch enroll-start --origin https://api.vaultperch.com \
  --keychain-profile courier-receiver --label courier-receiver
vaultperch enroll-complete --origin https://api.vaultperch.com \
  --keychain-profile courier-receiver

Between start and completion, use the app's receiver preview to compare the enrollment ID, label, pairing code and public-key thumbprint against the intended receiver over a trusted channel. Confirm the comparison, assign the workload principal and approve enrollment. The pairing code alone does not authorize approval. Complete only after approval; if pending, wait at least five seconds before another completion attempt. Private keys and polling/session tokens remain in receiver custody.

Existing custody limits apply: macOS requires a working unlocked Keychain. Explicit service-account file custody uses a distinct private 0700 directory and 0600 files for each owner or receiver, with --service-account-dir on every command instead of --keychain-profile; use a dedicated OS user for mutually untrusted workloads. Ubuntu 24.04 x64 / Node.js 24 runtime receiving passed a synthetic hosted DEV journey under amd64 emulation on an arm64 Docker host. That separate proof does not verify Linux courier use. Native Linux Secret Service remains unsupported.

4. Check one object and reconcile the original operation

vaultperch courier-head --origin https://api.vaultperch.com \
  --keychain-profile courier-receiver --credential CREDENTIAL_UUID \
  --resource RESOURCE_UUID --object-key readiness/check.txt \
  --operation-id HEAD_OPERATION_UUIDV7
vaultperch courier-status --origin https://api.vaultperch.com \
  --keychain-profile courier-receiver --operation-id HEAD_OPERATION_UUIDV7

courier-head requires an enrolled DPoP receiver with a current live broker:invoke grant, an active owned S3 credential at the bound version, an active matching resource and active account use. An owner login token cannot invoke it.

A completed operation contains either outcome: {status: "found", size: N} (0–5 TiB, in bytes) or outcome: {status: "not_found"}. A supported provider 404 is not_found; a denied or malformed provider response is an error, not absence. Safe errors include provider_denied, provider_invalid, provider_unknown, policy_denied, admission_expired and dependency_unavailable. No raw provider error text is returned.

A timeout, lost response, lost admission reply or persistence uncertainty may leave unknown. It does not prove that no provider request happened. Use courier-status with the original operation ID; it performs GET /v1/courier/operations/{operationId} and never sends a provider request. The current owner can also inspect it using the owner profile. The original principal may inspect historical safe receipts without its former use grant, but still needs current valid principal/enrollment/session authentication. After receiver revocation, use owner custody or a newly authorized enrollment of the original principal.

Do not automatically repeat HEAD or generate a new ID after ambiguity. Reusing an existing ID with the same intent only retrieves its recorded operation; it creates no new provider attempt or deadline. Changed intent under that ID conflicts. A deliberately distinct operation ID means a new read, including after failed, cancelled or unknown status. Make that choice explicitly after reviewing the original receipt; polling alone cannot resolve every unknown result.

5. Revoke and recover

vaultperch reauthenticate --origin https://api.vaultperch.com \
  --keychain-profile courier-owner
vaultperch courier-revoke --origin https://api.vaultperch.com \
  --keychain-profile courier-owner --resource RESOURCE_UUID \
  --operation-id REVOKE_OPERATION_UUIDV7

Resource revocation stops future admissions for that binding. Revoking a vault grant removes the principal's corresponding use authority; revoking a principal stops its receivers, and revoking one enrollment stops that receiver. Credential revocation stops future VaultPerch use of the credential. Current revocations and quarantine take precedence over an earlier grant or token. Revocation cannot retract an already dispatched provider request, delete an object or retire the upstream S3 credential. Rotate or revoke that credential at the provider separately when needed.

For a lost resource-enrollment or revocation response, list courier-resources, review metadata, and reconcile using the exact original command and operation ID if needed. Do not replace an ambiguous write with a different ID. HEAD receipt lookup does not serve as a resource-command receipt endpoint.

Follow the inventory restore guide for recovery. Restored courier resources remain inactive: review surviving owned credentials and create fresh owner bindings, fresh grants and receiver enrollments as needed before reviewed activation. Current Control revocations/admission facts are not rewound. Live courier receipts and cancellation tombstones survive restore, including newer operations; historical restored operations are receipts only and cannot dispatch again. A previously prepared operation becomes unknown. Restore does not make an old operation ID a new read.

Connect a client for the fixed courier check

Courier MCP is offered through separate explicit consent. A synthetic hosted DEV journey passed 38 checks, including real R2 found/missing responses, connection isolation, refreshed receipt lookup and revocation. This verifies the documented protocol; it does not establish named-host compatibility or actual-user demand.

Use the server URL https://api.vaultperch.com/mcp with an OAuth-enabled client registered for vaultperch.courier.head. A registration, authorization and connection has exactly one product capability: courier or vaultperch.metadata.read. Metadata is the default; an existing metadata connection cannot gain courier authority or switch capability through refresh. offline_access is optional for refresh access.

The protocol is stateless JSON Streamable HTTP, MCP 2025-11-25, with public OAuth discovery, dynamic client registration and S256 PKCE. Redirects must exactly match the registered HTTPS or literal loopback destination, including the actual loopback port. Compatibility with named hosts or untested SDKs is not claimed.

  1. Prepare the owned S3 credential and immutable resource using the owner steps above. Give the intended principal a current broker:invoke grant on the credential's vault. MCP does not import credentials, administer grants or create resource bindings. This courier connection performs the fixed check without a local receiver.
  2. Start a separate courier OAuth connection in the client. Sign in at the VaultPerch app and review the requesting client, registered destination, exact scope and expiry. Opening a request does not approve it.
  3. Choose one active principal and individually select the exact courier resources. Review the credential reference, vault, credential version, resource revision, R2 account, bucket, nonempty prefix and fixed courier.object.head@1 action. Confirm your password when requested, then explicitly allow the selected courier access. Resource/version/config changes require fresh consent; you can deny the request instead.
  4. Return to the client and list its current matching consented resources. Treat names and labels as untrusted text, not instructions.

Three tools and exact inputs

A courier connection exposes only list_courier_resources, courier_object_head and courier_operation_status. Metadata listing uses a separate metadata connection. Inputs accept no extra fields, arbitrary URL, method, header, signing options or secret values. The existing canonical prefix/key restrictions apply.

list_courier_resources takes an empty object and returns safe resource/binding metadata:

{}

courier_object_head takes exactly four strings: a lowercase UUIDv7 operationId, UUID credentialId and resourceId references, and an objectKey within the bound prefix. The following IDs are illustrative: replace the references with returned metadata and choose a new UUIDv7 before each deliberate new read, retaining it for status lookup.

{
  "operationId": "019a0000-0000-7000-8000-000000000001",
  "credentialId": "11111111-1111-4111-8111-111111111111",
  "resourceId": "22222222-2222-4222-8222-222222222222",
  "objectKey": "readiness/check.txt"
}

courier_operation_status takes exactly the original lowercase UUIDv7 operationId. It returns safe historical status and performs no provider request:

{"operationId": "019a0000-0000-7000-8000-000000000001"}

A completed read returns typed found with size in bytes or not_found, plus safe operation/receipt metadata. No credential value, object body, provider header, ETag or raw provider message is returned. Tool annotations and host tool approvals do not replace VaultPerch authorization.

Keep the original operation and connection

After a lost response or unknown, inspect the original operation through the same originating connection and principal. An unchanged duplicate HEAD only retrieves its recorded operation; changed intent under that ID conflicts. Never automatically repeat the read or replace its ID. A deliberately distinct ID means a new provider read. Unknown does not prove no request happened, and polling may not resolve it.

Receipt lookup is limited to that originating connection and consented binding. Sibling connections, another account and CLI receivers cannot inspect or cache an MCP-origin operation; courier MCP cannot inspect CLI-origin operations. The current owner can inspect safe receipts through the owner API as before.

Resource, credential or grant revocation stops new reads; an otherwise active original connection/principal can still inspect its historical receipt without the former use grant or active resource. Connection or principal revocation blocks its requests, including receipt access. Password reset or recovery that invalidates a connection requires fresh owner consent; restore does not revive OAuth access. Refresh cannot add capability or bypass revocation. Revocation cannot recall an already dispatched request or retire the upstream S3 credential.

Connection authority is shared across the client's host, chats and agents using that connection. It is scoped to the client, principal and selected resources, not to one chat. Use separate connections/principals for separate authority. Host approvals are separate. Never paste passwords, tokens or credential values into chat, tool arguments, configuration examples or support logs. Runtime credential delivery, handoff and owner administration are outside this MCP capability; native HOS remains upcoming.

Release scope

The fixed courier action is available through API/CLI with an enrolled receiver. The courier receiver proof uses macOS Keychain. Hosted Ubuntu runtime receiving is verified separately under emulation; Linux courier use remains unverified.

Hosted metadata MCP remains unchanged under its existing scope. The separate courier MCP setup above is offered through explicit consent for the fixed check; a metadata connection cannot invoke courier tools. Native HOS, native Linux Secret Service and a hosted Linux courier journey are not offered. Never send credential values through either MCP connection.