docs / cli / security

security & data transfer

security claim and scope

The CLI makes Castia control safer and more reviewable by placing the same authenticated, Organization-bound Operator API in front of humans, agents, and partner gateways. A CLI is not a security boundary by itself. Security depends on the caller, configured origin, credential handling, Operator authorization, Castia services, and any downstream provider.

This document covers the Operator API, CLI, human and service credentials, approval adapter, Microsoft/partner adapter preview, prompts and model input, external-provider uncertainty, and the package/update chain. It describes the implemented boundary and known residual risks; it is not a compliance certification.

The present safety limits are important:

  • campaign.launch@v1 binds exact human approval but starts no delivery. It returns deliveryStarted: false and sends zero messages.

  • Generic operation.retry@v1 is not advertised and the CLI's reserved retry grammar fails closed.

  • The Microsoft Copilot adapter is a contract preview, not a secure partner deployment. Entra identity, on-behalf-of (OBO) exchange, tenant policy, and deployment controls remain prerequisites.

  • campaign.audience.create@v1 and campaign.run.create@v1 create only pinned audiences and draft-only runs. They derive authority again before writing and never start delivery.

trust boundaries and protected assets

The boundaries are: secret store to caller process; package/update source to executable; caller or partner/model environment to the network; TLS termination to Operator authentication; authentication to capability policy; policy to durable ledger; and Castia services to external providers.

Protected assets include:

  • human and service credentials, PKCE verifiers, Organization bindings, and delegated-user identity;

  • tenant business data, Company/contact personal data, campaign content, playbook evidence, and provider configuration;

  • exact human approvals, scope fingerprints, idempotency keys, operation history, and audit attribution;

  • prompt/model inputs and tool outputs that may carry confidential or adversarial text;

  • CLI package integrity, trusted origins, local profiles, and security-relevant configuration.

implemented boundary and credential controls

The implemented client and server boundary provides:

  • HTTPS-only origins. HTTP is allowed only for 127.0.0.1 tests when CASTIA_ALLOW_INSECURE_LOOPBACK=1 is set.

  • No HTTP redirects; the caller must name the final trusted origin.

  • Bearer credentials sent in headers, never in URLs.

  • Explicit X-Castia-Organization binding, revalidated against the credential on every request.

  • Human membership/workspace revalidation and service-token role, scope, expiry, revocation, and delegated-user revalidation.

  • JSON input capped at 64 KiB, ordinary responses capped at 1 MiB, streams capped at 16 MiB, and NDJSON lines capped at 1 MiB.

  • Versioned response envelopes and bounded, allowlisted safe projections.

  • Token/secret redaction from human, JSON, JSONL, error, and hostile-server output.

  • Exact revision, scope fingerprint, idempotency, and durable operation receipts for mutations.

  • Human-only approval actions. A service identity cannot manufacture human authority.

EnvironmentSupported credential storage
macOSLogin Keychain through /usr/bin/security
Linux desktopSecret Service through secret-tool
WindowsCurrent-user DPAPI through non-interactive PowerShell
Headless agent/CICASTIA_TOKEN injected for one process by a trusted secret manager

The local config stores only profile names, Castia origins, and Organization IDs at mode 0600; secret-shaped fields are rejected. CASTIA_TOKEN takes precedence for the current process and is never persisted by the CLI.

Human device login uses a short-lived code, PKCE S256, an authenticated browser session, explicit Organization selection, and a 30-day Organization-bound credential. The server revalidates the human's current role, active membership, and workspace access.

Service credentials belong to exactly one Organization. Operators should issue separate, expiring, least-scope tokens per agent and environment and optionally bind each token to an active acting user. A human admin with operation:approve may approve or reject only the exact current operation fingerprint. Draft approval/rejection also requires a human actor; a service token cannot manufacture human authority.

threats, controls, and residual risks

SurfaceThreatsImplemented or required controlsResidual risk
Operator APICross-tenant object access, confused Organization binding, schema abuse, oversized payloads, replay, and secret leakage in errorsCredential and Organization revalidation on every request; role/scope/workspace policy; strict schemas and size caps; safe projections; deterministic idempotency; redaction; durable receiptsCastia terminates TLS and sees plaintext. Application, database, logging, deployment, and incident controls still matter.
CLI processToken theft, malicious origin, redirect credential forwarding, unsafe config permissions, terminal/log disclosure, and hostile response contentOS secret stores or vault injection; HTTPS and redirect refusal; 0600 non-secret config; bounded responses; redaction in all output modesA compromised device, shell, extension, subprocess, or administrator can still read process memory or user-visible business data.
Human credentialStolen browser/device credential, stale role, or authorization after membership removalPKCE device login; Organization binding; current membership, role, and workspace revalidation; expiry and revocationThirty-day credentials increase exposure until expiry or revocation; device posture is outside the CLI.
Service credentialExcessive scopes, shared-account attribution, unattended exfiltration, or long-lived agent compromiseOrganization-bound token; least role/scopes; expiry/revocation; optional active delegated user; separate tokens per agent/environmentA valid broad token can exercise every capability its policy permits. Vault, job, egress, and rotation controls remain external.
Approval adapterService self-approval, stale approval reuse, changed scope after review, or a human approving an unreadable targetHuman-only approval/rejection; admin plus operation:approve; exact scope fingerprint and revision; safe review projection; durable attributionA legitimate human can still make a bad decision. Review UX, separation of duties, and organization policy remain necessary.
Microsoft/partner adapterShared service-account actions, prompt injection, capability overreach, tenant confusion, tool-output exfiltration, or misleading deployment claimsAdapter-specific routes enforce the matrix-derived allowlist before the shared Operator; tenant/role/scope/revision checks remain mandatory; partner gateway must minimize fields and keep tokens out of promptsCurrent preview has no Entra/OBO user mapping or tenant deployment proof. The allowlist narrows tools but does not provide per-user Microsoft attribution.
Prompts and model inputCustomer data or tokens copied into prompts, malicious business text steering tool calls, provider retention/training, and untrusted model outputNever place tokens in prompts; classify and minimize allowed fields; treat model output as untrusted input; schema validation; capability discovery; human approval for governed effectsModel/provider telemetry, retention, subprocessors, residency, and prompt-injection behavior require separate contractual and technical review.
External providersFalse success, timeout after side effect, duplicate work, partial results, provider credential exposure, or policy driftDurable operations; idempotency; held and outcome_uncertain states; explicit provider readiness/policy checks where present; separate downstream incident reviewcompany.research@v1 uses an external dependency. No campaign-delivery adapter is connected, so delivery security and exactly-once behavior are unproven.
Package/update chainTyposquatting, registry/account compromise, tampered dependency or artifact, unreviewed auto-update, and stale vulnerable versionsUse only @castia/cli or a reviewed local package; lockfile and source review; reproducible test/pack verification; no curl | sh installationPublication, signing/provenance, maintainer security, registry policy, vulnerability response, and update rollout must be established before broad distribution.

For a regulated partner, add an approved data-processing agreement, data classifications, residency/retention decisions, partner-device and egress controls, audit export, provider review, incident response, and an explicit prompt policy. The wrapper may reduce exposure; it cannot weaken or replace Operator authorization and it cannot make the entire transfer end-to-end encrypted.

capability data-flow inventory

Classifications used below are: security (credentials, authorization and approval controls), operational (IDs, revisions, status, timestamps and cursors), business confidential (Company, playbook, campaign and research content), and personal data (identifiable contacts or users). Every request also carries a bearer credential and Organization ID as security data; credentials are validated but never returned. Mutation outputs are durable safe receipts unless stated otherwise.

CapabilityInput fields and classificationOutput fields and classificationExplicitly omitted
campaign-run.show@v1Operational: run ID and view; security: Organization bindingOperational and business confidential: safe review, evidence, or audit projection with run state, pins, counts, revisions, and decisionsOmitted: credentials, mailbox/provider secrets, unrestricted contact records, and other tenants
campaign.audience.create@v1Operational: Segment Playbook Version ID and idempotency key; business confidential and possible personal data: name, cold/warm relationship, and 1–20 visible target Company IDs with optional contact IDsOperational and business confidential: receipt followed by safe audience ID, member count, Segment Playbook Version ID, and frozen authority revisionOmitted: credentials, actor/role/tenant authority, full contact payloads, provider secrets, internal playbook authority, and other tenants
campaign.audience.freeze@v1Operational: run ID, expected revision, and idempotency keyOperational: receipt for the immutable frozen audience scope and scope fingerprintOmitted: credentials, raw contact bodies, mailbox/provider secrets, and other tenants
campaign.drafts.generate@v1Operational: run and target IDs plus expected revision; business confidential and possible personal data: subject and bodyOperational: receipt, revision, status, and scope fingerprintOmitted: credential, stored message body, model prompt/transcript, provider secrets, and other tenants
campaign.hold@v1Operational and business confidential: run ID, expected revision, idempotency key, and hold reasonOperational: receipt for the held scopeOmitted: credentials, unrelated campaign content, provider secrets, and other tenants
campaign.launch@v1Operational and security: run ID, expected revision, idempotency key, frozen scope, and exact human approval fingerprintOperational: approval-bound receipt; current result explicitly reports deliveryStarted: falseOmitted: credentials, provider secrets, delivery payloads, and other tenants; no messages are sent
campaign.outcome.record@v1Operational: run ID, expected revision, target ID, and allowlisted outcome kindOperational and business confidential: receipt for the recorded outcomeOmitted: credentials, message content, raw provider event, unsupported outcome fields, and other tenants
campaign.prepare@v1Operational: run ID, expected revision, idempotency key, and server-resolved frozen planOperational and business confidential: receipt for the immutable prepared batchOmitted: credentials, provider secrets, unapproved mutable state, and other tenants
campaign.resume@v1Operational: held run ID, expected revision, and idempotency keyOperational: receipt for the new immutable child batchOmitted: credentials, completed work, provider secrets, and other tenants
campaign.run.create@v1Operational: audience ID and idempotency key; business confidential: name, manual/personal-draft channel, 1–2 message variants with body templates capped at 3,500 characters each, optional angle/routing, and bounded personal-draft mailbox selection/scheduleOperational and business confidential: receipt followed by safe run ID, audience ID, draft state, Segment Playbook Version ID, and frozen authority revisionOmitted: credentials, mailbox owner/credential, provider fields, raw provider responses, internal playbook/settings authority, and other tenants; creation sends nothing
capability.list@v1Operational: API version and capability resource; security: caller scopes determine authorizationOperational: versioned capability IDs, roles, scopes, schemas, effects, and approval metadataOmitted: credentials, tenant business records, internal handlers, and unadvertised capabilities
company.archive@v1Operational and security: Company ID, expected revision, idempotency key, and exact human approval scopeOperational: receipt for soft archiveOmitted: credentials, Company content, hard-delete controls, and other tenants
company.followup.schedule@v1Operational and business confidential: Company ID, expected revision, date, reason and temperature; possible personal data: draft messageOperational: receipt for the scheduled follow-upOmitted: credentials, mailbox secrets, provider delivery response, and other tenants
company.import@v1Business confidential: URL/domain and name; personal data: optional contact name, email and role; operational: idempotency keyOperational: import/de-duplication receipt and resulting operation statusOmitted: credentials, duplicate candidate internals, enrichment/provider secrets, and other tenants
company.list@v1Operational: cursor and limitOperational and business confidential: Company ID, name, domain, status, lead score, owner user ID, revision, and next cursorOmitted: credentials, contacts, notes, raw research, provider data, and other tenants
company.research@v1Operational and business confidential: Company ID, expected revision, optional campaign play ID, and idempotency keyOperational: receipt for the governed external research attempt; research is stored behind its own bounded surfacesOmitted: credentials, provider secrets, raw provider payload/transcript, and other tenants
company.show@v1Operational: Company IDOperational and business confidential: ID, name, domain, status, lead score, owner user ID, and revisionOmitted: credentials, contacts, notes, raw research, provider data, and other tenants
credit-controls.show@v1Security: Organization-bound admin actor with credits:read; operational: read-only control-status requestOperational: read-only writesSupported: false statusOmitted: credentials, balance mutations, credit purchases/top-ups, Stripe actions, grant controls, and other tenants
credits.show@v1Security: Organization-bound admin actor with credits:read; operational: read-only balance requestOperational and business confidential: read-only balance, allowance, cycle spend, reset/renewal, pricing model, and automation/block statusOmitted: credentials, raw ledger rows, Stripe customer data/actions, balance mutations, purchase/top-up and grant controls, and other tenants
draft.approve@v1Operational and security: run/target ID, revision ID and number, content hash, expected revision, and human identityOperational: human-attributed decision receiptOmitted: credentials, approved message body, model prompt/transcript, and other tenants
draft.reject@v1Operational, security and business confidential: run/target ID, revision ID and number, content hash, reason, expected revision, and human identityOperational: human-attributed rejection receiptOmitted: credentials, rejected message body, model prompt/transcript, and other tenants
draft.revise@v1Operational: run/target ID and prior revision; business confidential and possible personal data: subject and bodyOperational: immutable new-revision receiptOmitted: credentials, prior message bodies, model prompt/transcript, provider secrets, and other tenants
icp.list@v1Operational and business confidential: cursor, limit, and optional searchOperational and business confidential: published ICP IDs, names, keys, kind, revision, sequence, action, publication time, and next cursorOmitted: credentials, unpublished criteria/evidence, personal contacts, and other tenants
icp.show@v1Operational: published ICP selection IDOperational and business confidential: published ICP identity, revision/publication metadata, name, key, kind, and statusOmitted: credentials, unpublished criteria/evidence, personal contacts, and other tenants
operation.approve@v1Operational and security: operation ID, expected revision, exact scope fingerprint, and human admin identityOperational: human-attributed approval receipt and updated statusOmitted: credentials, unrestricted target data, changed/stale scopes, and other tenants
operation.cancel@v1Operational and security: operation ID, expected revision, and exact scope fingerprintOperational: cancellation receipt and updated statusOmitted: credentials, unrestricted operation input/result, completed external effects, and other tenants
operation.follow@v1Operational: operation ID and optional after cursorOperational: bounded NDJSON events with cursor, sequence, type, status, timestamp, and safe dataOmitted: credentials, authorization headers, unrestricted payloads/errors, and other tenants
operation.reject@v1Operational, security and business confidential: operation ID, expected revision, exact scope fingerprint, reason, and human admin identityOperational: human-attributed rejection receipt and updated statusOmitted: credentials, unrestricted target data, changed/stale scopes, and other tenants
operation.show@v1Operational: operation IDOperational and business confidential: action, status, revision, safe target, fingerprint, review, timestamps, and bounded result/errorOmitted: credentials, raw authorization, internal stack traces, unrestricted payloads, and other tenants
segment-playbook-version.list@v1Operational and business confidential: cursor, limit, and optional searchOperational and business confidential: published version identity, commercial goal, audience pin, offering/blueprint pin summary, revision, publication time, and next cursorOmitted: credentials, unpublished playbook content, provider secrets, personal contacts, and other tenants
segment-playbook-version.show@v1Operational: Segment Playbook Version IDOperational and business confidential: published version identity, commercial goal, audience and offering/blueprint pins, revision, and publication timeOmitted: credentials, unpublished playbook content, provider secrets, personal contacts, and other tenants
usage-event.list@v1Security: Organization-bound admin actor with credits:read; operational: opaque cursor and limit for a read-only ledger requestOperational and business confidential: read-only bounded ledger entries with amount, kind, source, pricing SKU/version, timestamp, and next opaque cursorOmitted: credentials, internal ledger IDs, raw billing/provider records, write/top-up/grant controls, and other tenants
usage.show@v1Security: Organization-bound admin actor with both billing:read and credits:read; operational: optional 1–365 day window for a read-only requestOperational and business confidential: read-only usage window, spend, balance, allowance, burn rate, reset/renewal, pricing model, and automation/block statusOmitted: credentials, raw ledger rows, Stripe customer data/actions, balance mutations, purchase/top-up and grant controls, and other tenants
work.list@v1Operational: optional needs-human filter, cursor, and limitOperational and business confidential: bounded tenant work summaries, status, target, fingerprint, review, and timestampsOmitted: credentials, unrestricted operation input/result, provider secrets, and other tenants

Microsoft Copilot preview allowlist

The preview exposes an OpenAPI-compatible description and adapter-specific routes for a closed partner gateway. The routes enforce the list derived from operatorCoverageAllowlist("microsoft-copilot") before delegating to the shared Operator. A generic credential used against the core Operator routes is not confined to this partner list, so a production gateway must use the adapter routes and restrict egress accordingly. A live deployment still needs per-user Entra identity with OBO token exchange, tenant/admin consent, DLP, approved data classes, residency/retention, audit, disable/uninstall, and incident controls.

The gateway must keep Castia credentials outside prompts, send only fields approved for the partner's data class, treat Copilot text as untrusted, and let Castia revalidate Organization, role, scope, revision, and approval on every call. The current service-token preview does not advertise human-only approve/reject; those actions require a future Entra/OBO mapping to a live Castia human actor.

CapabilityInput fields and classificationOutput fields and classificationExplicitly omitted
capability.list@v1Operational: API version and discovery requestOperational: allowlisted capability contracts and schemasOmitted: Castia token, internal handlers, unadvertised capabilities, and tenant records
company.list@v1Operational: cursor and limitOperational and business confidential: bounded Company summary pageOmitted: token, contacts, notes, raw research, prompts, and other tenants
company.show@v1Operational: Company IDOperational and business confidential: bounded Company summaryOmitted: token, contacts, notes, raw research, prompts, and other tenants
icp.list@v1Operational and business confidential: cursor, limit, and searchOperational and business confidential: published ICP summary pageOmitted: token, unpublished evidence, personal contacts, prompts, and other tenants
icp.show@v1Operational: published ICP IDOperational and business confidential: published ICP summaryOmitted: token, unpublished evidence, personal contacts, prompts, and other tenants
operation.cancel@v1Security and operational: operation ID, exact fingerprint/revisionOperational: cancellation receiptOmitted: token, unrestricted target content, completed effects, and other tenants
operation.follow@v1Operational: operation ID and cursorOperational: bounded event streamOmitted: token, raw headers, unrestricted payloads/errors, and other tenants
operation.show@v1Operational: operation IDOperational and business confidential: bounded review/status projectionOmitted: token, raw input, internal stack trace, and other tenants
segment-playbook-version.list@v1Operational and business confidential: cursor, limit, and searchOperational and business confidential: published playbook pin summariesOmitted: token, unpublished content, personal contacts, prompts, and other tenants
segment-playbook-version.show@v1Operational: published version IDOperational and business confidential: published playbook pin summaryOmitted: token, unpublished content, personal contacts, prompts, and other tenants
work.list@v1Operational: needs-human filter, cursor, and limitOperational and business confidential: bounded work summariesOmitted: token, unrestricted payloads, provider secrets, prompts, and other tenants

troubleshooting & revocation the cli guide docs home