# Bun Protocol — AI Agent Interface (llms.txt) Base URL: {base_url}/v1 Auth: Bearer or cookie bun_session ## Endpoints - POST /runtime/operations - invoke any operation - GET /protocol/operations - list all operations with schemas ## Response envelope {status: ok|denied|failed|indeterminate, data?: {...}, error?: {code, message}} ## Status semantics - ok: success, data authoritative - denied: auth/permission failed - NEVER retry - failed: could not complete - may retry depending on code - indeterminate: outcome unknown - NEVER retry blindly, must reconcile ## Status of this protocol Every operation is stability: BETA. The project is NOT DEPLOYABLE and no commercial provider in the catalogue is PROVEN. Do not describe any operation as stable or GA, and do not claim a provider works. ## Operations (55 across 16 families) ### audit - bun.audit.query(operation_id?, status?, since?, limit?) -> {records, total_count} [auth, tenant, perms=audit:read] - bun.audit.record(operation_id, decision_id, classification?, hashes?, counts?, status?, error_code?) -> {record_id, operation_id, status, prev_hash?} ### context - bun.context.describe() -> {project_name?, stack_verdict?, frontend?, backend?, database?, frontend_components_count?, frontend_routes_count?, backend_routes_count?, backend_models_count?, detection_known?, detection_inferred?, detection_unresolved?, placed_operations?, recommended_operations?, human_decisions?, unresolved_questions?, source_identity_hash?} [auth, tenant, perms=context:read] - bun.context.missing() -> {not_yet_placed?, recommended_not_placed?, human_decisions?, unresolved?, total_missing?} [auth, tenant, perms=context:read] - bun.context.operations() -> {placed?, recommended?, total_placed?, total_recommended?, by_component?} [auth, tenant, perms=context:read] - bun.context.stack() -> {observed?, inferred?, stack_verdict?, project_name?} [auth, tenant, perms=context:read] ### credential - bun.credential.describe(credential_id) -> {credential_id, credential_type, project_id, environment_id, state, issued_at, expires_at, last_used_at?, description?} [auth] - bun.credential.issue(project_id, environment_id, credential_type, description?, ttl_hours?) -> {credential_id, credential_type, authenticator, project_id, environment_id, expires_at} [auth] - bun.credential.revoke(credential_id, reason?) -> {credential_id, revoked} [auth] - bun.credential.rotate(credential_id, authenticator, ttl_hours?) -> {new_credential_id, authenticator, credential_type, project_id, environment_id, expires_at} - bun.credential.validate(credential_id, authenticator, expected_project_id?, expected_environment_id?, expected_type?) -> {valid, credential_id?, credential_type?, project_id?, environment_id?, reason?} ### data - bun.data.bulk(resource_type, records) -> {resource_type, created, failed, ids, errors} [auth, tenant, perms=data:write] - bun.data.create(resource_type, data?, resource_id?, retain_until?) -> {resource_type, resource_id, data, data_version?, ownership_version?, retain_until?} [auth, tenant, perms=data:write] - bun.data.delete(resource_type, resource_id) -> {resource_type, resource_id, deleted} [auth, tenant, perms=data:write] - bun.data.get(resource_type, resource_id) -> {resource_type, resource_id, data?, found?, data_version?, ownership_version?, retain_until?, expired?} [auth, tenant, perms=data:read] - bun.data.list(resource_type, filters?, cursor?, limit?, sort_by?, sort_order?) -> {resource_type, records, cursor?, total_count} [auth, tenant, perms=data:read] - bun.data.query(resource_type, filters?, cursor?, limit?, sort_by?, sort_order?) -> {resource_type, records, cursor?, total_count} [auth, tenant, perms=data:read] - bun.data.read(resource_type, resource_id) -> {resource_type, resource_id, data?, found?, data_version?, ownership_version?, retain_until?, expired?} [auth, tenant, perms=data:read] - bun.data.update(resource_type, resource_id, data) -> {resource_type, resource_id, data?, updated?, data_version?, ownership_version?} [auth, tenant, perms=data:write] ### deploy - bun.deploy.apply(deployment_id) -> {deployment_id, state, applied_at?, result?} [auth, perms=deploy:write] - bun.deploy.describe(target_application, operations?) -> {target_application, operation_count, available_operations, description} [auth, perms=deploy:read] - bun.deploy.plan(target_application, operations, config?) -> {deployment_id, target_application, state, plan, plan_checksum, operation_count, created_at} [auth, perms=deploy:write] - bun.deploy.rollback(deployment_id, reason?) -> {deployment_id, state, rolled_back_at?, reason} [auth, perms=deploy:write] - bun.deploy.status(deployment_id) -> {deployment_id, target_application, state, plan_checksum, created_at, updated_at, result?} [auth, perms=deploy:read] ### file - bun.file.access(file_id, purpose, decrypt?) -> {file_id, found, file_name?, content_type?, file_data_b64?, stored_hash?, decrypted?} [auth, tenant, perms=file:read] - bun.file.delete(file_id) -> {file_id, deleted} [auth, tenant, perms=file:write] - bun.file.sign(file_id, ttl_seconds?) -> {file_id, signed_token, expires_at, ttl_seconds, tenant_id} [auth, tenant, perms=file:read] - bun.file.upload(resource_type, resource_id, file_data_b64, file_name?, content_type?, metadata?) -> {file_id, resource_type, resource_id, stored_hash, key_version, ciphertext_size_bytes} [auth, tenant, perms=file:write] ### identity - bun.identity.current() -> {authenticated, subject_id, display_name?, tenant_id?, role?, permissions?, subscription_plan?, subscription_active?} - bun.identity.login(email, password) -> {subject_id, session_token, provider?} - bun.identity.register(email, password?) -> {subject_id, session_token, provider?} ### membership - bun.membership.accept(invite_code) -> {tenant_id, role, joined_at} [auth] - bun.membership.invite(email?, role?) -> {invite_code, tenant_id, expires_at} [auth, tenant, perms=membership:invite] - bun.membership.revoke(subject_id) -> {revoked, subject_id, tenant_id} [auth, tenant, perms=membership:revoke] ### message - bun.message.redact(message_id, redact_recipient?, redact_template_data?) -> {message_id, redacted, recipient_redacted, template_data_redacted, error?} [auth, tenant, perms=message:send] - bun.message.send(recipient, template, template_data?, provider?, idempotency_key?) -> {message_id, status, provider_message_id?, error?} [auth, tenant, perms=message:send] - bun.message.status(message_id) -> {message_id, found, status?, provider_message_id?, sent_at?, redacted?} [auth, tenant, perms=message:send] ### permission - bun.permission.check(resource, action, require_tenant?) -> {allowed, reason, decision_id} [auth] ### provider - bun.provider.connect(category, provider_key, credentials?, config?, region?) -> {status, provider_key, category, display_name, message, setup_mode?, region?} [auth, tenant, perms=provider:connect] - bun.provider.disconnect(category) -> {status, category, provider_key?, message, region?} [auth, tenant, perms=provider:disconnect] - bun.provider.health(category) -> {status, category, provider_key?, message, checked_at, latency_ms?, detail?, region?, recent_operations?} [auth] - bun.provider.list_categories() -> {categories} [auth] - bun.provider.list_providers(category) -> {category, providers} [auth] - bun.provider.switch(category, from_key, to_key, credentials?, config?, region?, mode?) -> {from_provider, to_provider, category, status, switch_difficulty, message, manual_steps?, region?, mode?, plan?, dry_run_checks?, missing_evidence?, mutated?, old_provider_retained?} [auth, tenant, perms=provider:connect] ### session - bun.session.revoke(all_sessions?) -> {revoked, revoked_count} [auth] - bun.session.validate() -> {valid, subject_id?, reason?} ### subscription - bun.subscription.require_active(feature_key?) -> {active, plan?, status?, feature_allowed?} [auth] ### system - bun.system.describe_context() -> {protocol_version, supported_operations, server_time} - bun.system.ping(message?) -> {message, server_time, protocol_version?} ### tenant - bun.tenant.create(name, description?, slug?) -> {tenant_id, name, slug, created_at} [auth] - bun.tenant.current() -> {tenant_id?, name?, slug?, role?} [auth] ### webhook - bun.webhook.deduplicate(provider, event_id) -> {is_duplicate, provider, event_id, existing_receipt_id?} - bun.webhook.order_check(provider, nonce) -> {provider, nonce, accepted, last_nonce?, reason?} - bun.webhook.receive(provider?, event_type, event_id, raw_body, signature_header, timestamp, scheme?, nonce?) -> {receipt_id, provider, event_type, deduplicated, status, tenant_id?, nonce_accepted?} - bun.webhook.verify(raw_body, signature_header, timestamp, provider?, scheme?) -> {verified, provider, reason?, scheme?}