{
  "schemaVersion": "1.0",
  "title": "Build a connector",
  "description": "Use this guide to turn a bounded provider API into an AIP connector crate and a standalone connector-host binary. It is for Rust developers who own the provider mapping and can coordinate release, security, and deployment evidence.",
  "canonical": "https://getaip.org/docs/guides/build-a-connector",
  "route": "/docs/guides/build-a-connector",
  "source": "docs/guides/build-a-connector.md",
  "protocol": "Agent Interoperability Protocol",
  "protocolVersion": "1.0",
  "section": "Connectors",
  "documentType": "Guide",
  "language": "en",
  "revision": {
    "lastReviewedRevision": "d7cce13d1d555644d04a4d73c66c95b113737635",
    "documentationSourceRevision": "9192fef3695ad294994f2712f6d156241e5e92fb",
    "basis": "frontmatter"
  },
  "downloads": {
    "md": "/docs/download/guides/build-a-connector.md",
    "txt": "/docs/download/guides/build-a-connector.txt",
    "json": "/docs/download/guides/build-a-connector.json",
    "pdf": "/docs/download/guides/build-a-connector.pdf"
  },
  "content": {
    "format": "text/markdown",
    "markdown": "---\ntitle: Build a connector\ndescription: Build a bounded AIP connector and standalone host for fleet admission\nkind: how-to\naudience: developer\nappliesTo: \"1.x\"\nwritingStandard: \"aip-docs/1.0\"\nlastReviewedRevision: \"d7cce13d1d555644d04a4d73c66c95b113737635\"\n---\n\n# Build a connector\n\nUse this guide to turn a bounded provider API into an AIP connector crate and a\nstandalone connector-host binary. It is for Rust developers who own the provider\nmapping and can coordinate release, security, and deployment evidence.\n\nThe result of this procedure is a candidate connector artifact. Source code, a\nsuccessful build, or a reachable health endpoint does not by itself establish\nadmission, conformance, qualification, live-product compatibility, or production\nreadiness.\n\nThis guide describes the implementation at source revision\n`d7cce13d1d555644d04a4d73c66c95b113737635`. It covers AIP 1.0 and the frozen\nconnector SDK boundary used by the connector fleet.\n\n## Use this procedure for a provider boundary\n\nBuild a connector when an external product has a stable operation or event\nsurface that AIP needs to expose as capabilities. One connector type should own\none implementation family. One connector instance should own one tenant-scoped\nprovider account, workspace, application, endpoint set, or equivalent boundary.\n\nDo not build a connector when the requirement is only to:\n\n- translate AIP into MCP or A2A framing;\n- add a trusted in-process module with no external product boundary;\n- expose arbitrary caller-selected URLs, paths, headers, or credentials;\n- rename an existing connector capability without changing its provider\n  contract.\n\nCheck the [connector catalog](../connectors/README.md) first. Extend an existing\nconnector when it already owns the provider boundary.\n\n## Prepare access and design inputs\n\nComplete these prerequisites before changing the workspace:\n\n- select the exact AIP source revision and Rust toolchain for the release;\n- obtain the provider API specification and pin its version or revision;\n- obtain a non-production provider account with the minimum required scopes;\n- identify who may create credentials, webhooks, release signatures, evidence,\n  admission packages, and tenant bindings;\n- define where durable runtime, replay, idempotency, and reconciliation state\n  will be stored;\n- choose an immutable artifact format and digest;\n- define a test topology that cannot affect production data.\n\nTreat provider credentials, webhook secrets, signing seeds, database URLs, and\nprivate trust roots as deployment-owned secrets. They do not belong in source,\nthe AIP manifest, capability input, registry catalog values, evidence payloads,\nlogs, or documentation examples.\n\nBefore implementation, write a short boundary record:\n\n| Input | Decision to record | Why it matters |\n|---|---|---|\n| Provider identity | Product, API version, and upstream revision | Prevents an unbounded or moving API surface |\n| Account boundary | Tenant plus provider account, workspace, app, or endpoints | Defines isolation and idempotency scope |\n| Operation inventory | Exact reads, writes, deletes, messages, and long-running calls | Drives capabilities, risk, and approval |\n| Authentication | Credential kind, required scopes, and rotation owner | Keeps caller input out of the secret boundary |\n| Completion model | Synchronous, asynchronous, streaming, or provider job | Determines runtime and recovery behavior |\n| Mutation behavior | Idempotency, retry, cancellation, reconciliation, compensation | Prevents duplicate or uncertain side effects |\n| Ingress | Webhooks, signatures, timestamps, nonce, replay state, and limits | Defines the authenticated event boundary |\n| Release evidence | Build, SBOM, provenance, conformance, and policy owners | Makes artifact admission reviewable |\n\nStop if any mutation has unknown retry behavior and no conservative failure\npolicy. A connector can publish fewer capabilities while the missing contract is\nresolved.\n\n## Create separate connector and host packages\n\nKeep product mapping separate from deployment composition:\n\n```text\ncrates/\n├── aip-connector-provider-name/\n│   ├── Cargo.toml\n│   ├── src/\n│   │   ├── lib.rs\n│   │   └── operations.rs\n│   └── tests/\n│       ├── connector_contract.rs\n│       └── frozen_conformance.rs\n└── aip-host-provider-name/\n    ├── Cargo.toml\n    └── src/\n        └── main.rs\n```\n\nReplace `provider-name` with the stable product identifier. Register both\npackages as workspace members and workspace dependencies.\n\nThe connector package normally depends on `aip-connector`, `aip-core`,\n`aip-discovery`, `aip-runtime`, `async-trait`, `serde_json`, and the\nbounded HTTP or sidecar client needed by the product. Add `aip-conformance` and\nschema tooling as development dependencies when the test driver uses them.\n\nThe host package depends on the product connector and the common\n`aip-connector-host` and `aip-connector-host-bootstrap` boundaries. Add\nrouting or durable-store types only when product-owned ingress needs them.\nDo not embed the connector into the product-neutral `getaip-server` binary.\n\nUse the connector crate for:\n\n- provider configuration validation;\n- capability and manifest construction;\n- request and response mapping;\n- typed failure classification;\n- provider-specific idempotency, cancellation, and reconciliation;\n- signed webhook validation before an event enters AIP.\n\nUse the host crate for:\n\n- parsing deployment configuration;\n- reading owner-controlled secret files;\n- constructing the product client;\n- binding durable provider-specific stores;\n- starting the common host lifecycle;\n- mounting authenticated product ingress when required.\n\n## Publish an honest manifest\n\nImplement `Connector` with a stable `id`, `discover`, `map_error`, and an\nappropriate `health` probe. The returned `Manifest` carries the manifest\nversion, provider principal, capabilities, profiles, resources, channels,\nsecurity, governance, limits, compatibility, and extensions.\n\nEach callable capability needs a stable ID, input schema, optional output\nschema, and a contract that matches provider behavior. Record these properties\nbefore writing the provider call:\n\n| Contract area | What to declare |\n|---|---|\n| Side effects | Every applicable read, write, delete, send-message, financial, identity, medical, legal, external-network, or code-execution effect |\n| Idempotency | Whether a key is required, its scope, duplicate behavior, and retention when known |\n| Execution | Supported completion modes, cancellation, retry, and retry safety |\n| Data | Sensitivity, retention, residency, and redaction behavior |\n| Credentials | Required handle and scopes without secret material |\n| Approval | Whether approval is required and what evidence is retained |\n| Transactions | Implemented plan, commit, reconciliation, and compensation modes |\n\nDo not infer a safe contract from the HTTP method. A provider may implement a\n`POST` read, an asynchronous `DELETE`, or a write whose timeout leaves the\noutcome unknown.\n\nImplement `CapabilityProviderConnector` when callers or tests need the\ncapability list independently of the complete manifest. Return the same\ncapability definitions from both surfaces.\n\n## Match runtime support to the contract\n\nImplement `FrozenConnector` for the production execution boundary. Its\n`implementation_support` result is independent of the capability contract:\nthe contract says what the capability promises, while the support map says what\nthe current code implements.\n\nSet each support flag only when the corresponding path exists:\n\n- `invocation` for normal execution;\n- `cancellation` when cancellation reaches the provider operation;\n- `streaming` when incremental output reaches the runtime publisher;\n- `retry` when retry classification and downstream idempotency are enforced;\n- `transaction` for plan and commit;\n- `reconciliation` for unknown provider outcomes;\n- `compensation` for a separately governed compensation action;\n- `approval` for approval evidence and resume behavior;\n- `credentials` for deployment-resolved credential handles.\n\nThe discovery layer rejects claims such as streaming, cancellation, retry, or\ntransaction support when the implementation map does not support them. It also\nrejects a callable capability without an implementation claim when that\nadmission policy is enabled.\n\nEvery `FrozenConnector` operation receives `ActionExecutionContext`.\nAuthorize and scope the provider request from its authenticated actor, verified\ntenant, credential handle, deadline, cancellation token, idempotency reservation,\napproval evidence, transaction state, trace context, and redaction policy. Use\nthe supplied checkpoint and stream publishers for their declared purposes.\nDo not reconstruct authority from action input or metadata.\n\nThe host validates the signed gateway and the pinned route before it invokes the\nconnector. That host-level route check is not caller-controlled connector\nmetadata.\n\nThe frozen adapter rejects context-free execution. Keep that fail-closed\nbehavior; do not add a second path that calls the provider without trusted\ncontext.\n\nOperations that you do not implement already return\n`connector.operation_unsupported`. Override only the operations that the\nmanifest and support map advertise.\n\n## Map provider failures conservatively\n\nReturn `ConnectorFailure` from typed operations. Preserve a stable namespaced\ncode, a redacted message, AIP error category, retry decision, optional retry\ndelay, provider request ID, durable provider operation reference, remote\nstatus, unknown-outcome flag, redacted details, source component, and connector\noperation.\n\nUse the point of failure to decide retry and reconciliation:\n\n| Observation | Safe connector decision |\n|---|---|\n| Input rejected before dispatch | Permanent failure; no provider side effect |\n| Authentication or scope rejected | Non-retryable until credentials or policy change |\n| Provider rate limit on a retry-safe operation | Temporary and retryable with the provider delay when available |\n| Read failed before a response | Retry only when the capability contract permits it |\n| Mutation timed out after dispatch | Mark the outcome uncertain; do not report a safe blind retry |\n| Provider returned an operation ID | Retain it for status checks, cancellation, or reconciliation |\n| Cancellation won locally | Do not claim provider cancellation unless the remote endpoint confirmed it |\n| Response exceeded the configured bound | Fail closed and retain only redacted diagnostic data |\n\nNever place provider payloads, credentials, authorization headers, signing\nmaterial, or unbounded response bodies in `message` or\n`redacted_details`.\n\n## Protect secrets and provider destinations\n\nLoad credentials at the host boundary and wrap in `ConnectorSecret`.\n`ConnectorSecret` is non-serializable, redacts its debug output, compares in\nconstant time, and zeroizes owned bytes on drop. Expose its bytes only while\nconstructing the downstream request.\n\nValidate provider destinations before accepting credentials:\n\n- require HTTPS outside an explicit trusted development boundary;\n- reject embedded usernames, passwords, fragments, and unexpected base paths;\n- construct paths from admitted operations instead of caller-supplied URLs;\n- allow only documented query keys, headers, redirects, and response types;\n- apply request, response, timeout, and concurrency bounds;\n- keep account or workspace identity in deployment configuration.\n\nUse an opaque credential handle or secret-provider reference in registry and\nroute state. A credential revision may be pinned to a route so an in-flight\naction cannot silently switch credentials during rotation.\n\n## Add ingress only when the provider needs it\n\nMount product routes with the common host only for authenticated provider\ningress. Verify the signature over the exact raw body before JSON\nnormalization. Validate the provider timestamp and account identity, reject\nreplayed nonces or event IDs through durable state, and bound the body before\nparsing it.\n\nPersist the accepted AIP event before acknowledging delivery when the provider\nretry contract requires durability. Publish to the central event endpoint\nthrough the host outbox so a transient central failure does not require a\nsecond provider delivery.\n\nIngress routes remain in the product host. They do not expand the central\n`getaip-server` router or bypass the connector's tenant boundary.\n\n## Compose the standalone host\n\nFlatten `ConnectorHostBootstrapArgs` into the product host CLI. Product\narguments add the provider origin, account identity, credential-file paths,\nenabled-operation configuration, and product limits.\n\nThe common bootstrap requires:\n\n- the public native endpoint and narrow control-plane endpoint;\n- admitted connector type, version, instance, and replica IDs;\n- tenant and membership identity;\n- gateway and control-plane verification DIDs;\n- the exact immutable artifact digest;\n- a durable PostgreSQL URL file and host signing-seed file;\n- a non-secret secret-provider reference;\n- topology, capacity, lease, heartbeat, drain, and health bounds.\n\nThe recurring host sequence is:\n\n1. read and validate product configuration and secrets;\n2. construct the connector;\n3. call `PreparedConnectorHost::prepare`;\n4. attach durable product stores or authenticated ingress;\n5. call `serve`, `serve_with_router`, or `serve_with_router_factory`;\n6. resolve shutdown through `shutdown_signal`.\n\n`prepare` validates deployment identity, discovers the manifest, configures\nsigning and trust, opens durable storage, and constructs the control-plane\nclient. Serving then recovers durable runtime state, registers the replica,\nrenews its lease, exposes the common HTTP surface, drains, and marks the\nreplica offline.\n\nThe common surface is:\n\n| Route | Meaning |\n|---|---|\n| `GET /health` | Process and protocol identity only |\n| `GET /ready` | Lease, drain, durable storage, and connector readiness |\n| `GET /metrics` | Bounded connector-host metrics |\n| `GET /aip/v1/manifest` | Exact running manifest |\n| `POST /aip/v1/messages` | Signed, route-pinned native AIP execution |\n\nDo not use `/health` as a traffic gate. A host is ready only when `/ready`\nreturns success and the registry sees an eligible lease.\n\n## Prepare immutable admission\n\nBuild the host as an immutable artifact and record its digest. Generate the\nmanifest and implementation support map from the same source and configuration\nclass. A production admission package binds:\n\n- connector type and immutable version;\n- manifest and canonical manifest digest;\n- artifact digest and SDK version requirement;\n- implementation support for every callable capability;\n- admission policies, tenant-owned instances, pre-provisioned replicas, and\n  tenant capability bindings;\n- seven mandatory evidence families.\n\nThe evidence families are OCI signature, SBOM, provenance, conformance,\nvulnerability policy, license policy, and revocation observation. Each evidence\nstatement binds the artifact digest, manifest digest, document digest, signer,\noutcome, issue time, and expiration. Deployment trust policy supplies separate\nroots for the package and each evidence role.\n\nUse the short-lived operator workflow after the release system has produced and\nsigned the package:\n\n```sh\ngetaip connector registry plan \\\n  --package signed-admission.json \\\n  --trust-policy admission-trust-policy.json\n\ngetaip connector registry apply \\\n  --package signed-admission.json \\\n  --trust-policy admission-trust-policy.json \\\n  --database-url-file registry-database-url\n```\n\n`plan` verifies signatures, evidence, time bounds, digests, SDK compatibility,\nmanifest invariants, and registry relationships without writing. `apply`\nuses a durable journal and can resume the same package revision and digest\nafter interruption. A changed digest under the same identity is a conflict, not\nan update.\n\nDo not give the long-running connector host registry-administrator credentials.\n\n## Test the provider boundary\n\nUse layered tests so each result has a clear meaning:\n\n1. Unit-test identifiers, schemas, path construction, header construction,\n   redaction, response bounds, and failure mapping.\n2. Contract-test requests against a controlled provider stub. Include\n   idempotency collisions, reordered inputs, rate limits, timeouts, malformed\n   responses, and ambiguous mutation outcomes.\n3. Test webhook signatures, timestamps, replay fencing, account matching,\n   durable append, and central publication when ingress exists.\n4. Implement a `ConnectorConformanceDriver` and exercise every scenario\n   implied by the manifest and implementation support.\n5. Test host recovery, registration, lease loss, readiness, drain, offline\n   transition, credential rotation, and artifact mismatch.\n6. Run an isolated live-provider matrix only with an authorized test account and\n   retained evidence.\n\nThe frozen conformance model contains twelve scenario families. They cover\nidentity and credentials, schema enforcement, idempotency and duplicates, retry\nand exhaustion, cancellation races, streaming and backpressure, errors and\nuncertain outcomes, approval lifecycle, transaction lifecycle, audit and\nredaction, webhook security, and restart and reconnect.\n\nA scenario applies according to\nthe manifest and implementation support. An absent feature may make a scenario\nnot applicable; it must not be reported as a passed implementation.\n\nA source test demonstrates implementation behavior at that revision. Call a\nconnector qualified only when an exact artifact, topology, procedure, timestamp,\nand retained result satisfy the declared qualification scope.\n\n## Roll out with a bounded first binding\n\nUse this order for the first deployment:\n\n1. Prepare a signed package with one non-production tenant binding and a\n   conservative admission policy, then verify it with `plan`.\n2. Apply that exact signed admission package.\n3. Deploy one replica with the exact admitted artifact digest and pre-provisioned\n   identity.\n4. Wait for durable recovery, successful registration, a valid lease, and\n   `/ready`.\n5. Compare the running manifest with the admitted manifest digest.\n6. Discover the bound capability through the product-neutral gateway.\n7. Invoke a read-only or otherwise non-destructive qualification capability.\n8. Observe errors, lease state, capacity, latency, and retained audit evidence.\n9. Expand bindings or replicas only after the bounded result is accepted.\n\nUse `getaip connector test` for a basic host manifest check:\n\n```sh\nHOST_URL=https://connector.example.test\nCAPABILITY_ID=cap:twenty:metadata.list\n\ngetaip connector test \"$HOST_URL\" --capability \"$CAPABILITY_ID\"\n```\n\nThe command confirms that the deployed endpoint advertises the requested\ncapability. It does not prove tenant routing, provider execution, or\nqualification. This example deliberately omits `--invoke-capability`: a\nstandalone host accepts signed actions only from its configured central gateway.\nPerform action qualification through that authorized route with an input and\nside-effect boundary approved for the test environment.\n\n## Verify the completed connector\n\nBefore requesting catalog publication, confirm all of the following:\n\n- connector and host packages are separate and registered in the workspace;\n- the provider boundary and upstream revision are fixed;\n- manifest schemas and contracts match provider behavior;\n- implementation support matches every advertised feature;\n- typed execution uses trusted context and fails closed without it;\n- failure, retry, cancellation, and uncertain-outcome behavior is tested;\n- secrets stay in the host boundary and diagnostics remain redacted;\n- ingress is authenticated, replay-fenced, bounded, and durable when present;\n- the evidence and package reference the same artifact and manifest digests;\n- registry identities and the running replica match the admitted IDs;\n- the declared conformance and qualification scopes have retained results;\n- rollback has been rehearsed without discarding durable reconciliation state.\n\nRecord source revision, provider revision, artifact digest, manifest digest,\nadmission package ID and revision, tenant binding revision, test topology,\ntimestamps, and evidence locations.\n\n## Decide failures without widening risk\n\n| Failure | Decision |\n|---|---|\n| Manifest admission fails | Correct the manifest or implementation support; do not weaken policy to publish it |\n| Evidence is missing, stale, or mismatched | Rebuild the affected evidence for the exact artifact and manifest |\n| Host registers with a different ID or digest | Stop the replica and correct deployment identity |\n| `/health` succeeds but `/ready` fails | Inspect lease, drain, storage, and connector readiness before routing |\n| Provider authentication fails | Disable the binding or drain the replica before rotating credentials |\n| Mutation outcome is unknown | Preserve state and reconcile; do not send an unbounded retry |\n| Lease renewal becomes ambiguous | Let the host replay its fenced request; do not create an untracked replica |\n| Live-provider behavior differs from the contract | Disable the affected binding and reopen implementation review |\n\n## Roll back without losing evidence\n\nStop new assignments by disabling the affected tenant binding or revoking the\napplied package revision. Drain the host before termination so assigned actions\ncan finish within the configured deadline and the registry can record the\noffline transition.\n\nRetain the connector runtime database, provider operation references,\nidempotency records, admission journal, signed package, evidence, logs, and\nmetrics needed to resolve uncertain outcomes. Do not replace the artifact under\nan existing immutable version ID. Admit a corrected version and move bindings\nthrough a separately reviewed rollout.\n\n## Related documentation\n\n- [Capabilities](../concepts/capabilities.md)\n- [Profiles and connectors](../concepts/profiles-and-connectors.md)\n- [Identity and trust](../concepts/identity-and-trust.md)\n- [Trusted local modules](trusted-local-modules.md)\n",
    "text": "Build a connector\n\nUse this guide to turn a bounded provider API into an AIP connector crate and a\nstandalone connector-host binary. It is for Rust developers who own the provider\nmapping and can coordinate release, security, and deployment evidence.\n\nThe result of this procedure is a candidate connector artifact. Source code, a\nsuccessful build, or a reachable health endpoint does not by itself establish\nadmission, conformance, qualification, live-product compatibility, or production\nreadiness.\n\nThis guide describes the implementation at source revision\nd7cce13d1d555644d04a4d73c66c95b113737635. It covers AIP 1.0 and the frozen\nconnector SDK boundary used by the connector fleet.\n\nUse this procedure for a provider boundary\n\nBuild a connector when an external product has a stable operation or event\nsurface that AIP needs to expose as capabilities. One connector type should own\none implementation family. One connector instance should own one tenant-scoped\nprovider account, workspace, application, endpoint set, or equivalent boundary.\n\nDo not build a connector when the requirement is only to:\n• translate AIP into MCP or A2A framing;\n• add a trusted in-process module with no external product boundary;\n• expose arbitrary caller-selected URLs, paths, headers, or credentials;\n• rename an existing connector capability without changing its provider\n  contract.\n\nCheck the connector catalog (../connectors/README.md) first. Extend an existing\nconnector when it already owns the provider boundary.\n\nPrepare access and design inputs\n\nComplete these prerequisites before changing the workspace:\n• select the exact AIP source revision and Rust toolchain for the release;\n• obtain the provider API specification and pin its version or revision;\n• obtain a non-production provider account with the minimum required scopes;\n• identify who may create credentials, webhooks, release signatures, evidence,\n  admission packages, and tenant bindings;\n• define where durable runtime, replay, idempotency, and reconciliation state\n  will be stored;\n• choose an immutable artifact format and digest;\n• define a test topology that cannot affect production data.\n\nTreat provider credentials, webhook secrets, signing seeds, database URLs, and\nprivate trust roots as deployment-owned secrets. They do not belong in source,\nthe AIP manifest, capability input, registry catalog values, evidence payloads,\nlogs, or documentation examples.\n\nBefore implementation, write a short boundary record:\n\n| Input | Decision to record | Why it matters |\n\n| Provider identity | Product, API version, and upstream revision | Prevents an unbounded or moving API surface |\n| Account boundary | Tenant plus provider account, workspace, app, or endpoints | Defines isolation and idempotency scope |\n| Operation inventory | Exact reads, writes, deletes, messages, and long-running calls | Drives capabilities, risk, and approval |\n| Authentication | Credential kind, required scopes, and rotation owner | Keeps caller input out of the secret boundary |\n| Completion model | Synchronous, asynchronous, streaming, or provider job | Determines runtime and recovery behavior |\n| Mutation behavior | Idempotency, retry, cancellation, reconciliation, compensation | Prevents duplicate or uncertain side effects |\n| Ingress | Webhooks, signatures, timestamps, nonce, replay state, and limits | Defines the authenticated event boundary |\n| Release evidence | Build, SBOM, provenance, conformance, and policy owners | Makes artifact admission reviewable |\n\nStop if any mutation has unknown retry behavior and no conservative failure\npolicy. A connector can publish fewer capabilities while the missing contract is\nresolved.\n\nCreate separate connector and host packages\n\nKeep product mapping separate from deployment composition:\n\ncrates/\n├── aip-connector-provider-name/\n│   ├── Cargo.toml\n│   ├── src/\n│   │   ├── lib.rs\n│   │   └── operations.rs\n│   └── tests/\n│       ├── connectorcontract.rs\n│       └── frozenconformance.rs\n└── aip-host-provider-name/\n    ├── Cargo.toml\n    └── src/\n        └── main.rs\n\nReplace provider-name with the stable product identifier. Register both\npackages as workspace members and workspace dependencies.\n\nThe connector package normally depends on aip-connector, aip-core,\naip-discovery, aip-runtime, async-trait, serdejson, and the\nbounded HTTP or sidecar client needed by the product. Add aip-conformance and\nschema tooling as development dependencies when the test driver uses them.\n\nThe host package depends on the product connector and the common\naip-connector-host and aip-connector-host-bootstrap boundaries. Add\nrouting or durable-store types only when product-owned ingress needs them.\nDo not embed the connector into the product-neutral getaip-server binary.\n\nUse the connector crate for:\n• provider configuration validation;\n• capability and manifest construction;\n• request and response mapping;\n• typed failure classification;\n• provider-specific idempotency, cancellation, and reconciliation;\n• signed webhook validation before an event enters AIP.\n\nUse the host crate for:\n• parsing deployment configuration;\n• reading owner-controlled secret files;\n• constructing the product client;\n• binding durable provider-specific stores;\n• starting the common host lifecycle;\n• mounting authenticated product ingress when required.\n\nPublish an honest manifest\n\nImplement Connector with a stable id, discover, maperror, and an\nappropriate health probe. The returned Manifest carries the manifest\nversion, provider principal, capabilities, profiles, resources, channels,\nsecurity, governance, limits, compatibility, and extensions.\n\nEach callable capability needs a stable ID, input schema, optional output\nschema, and a contract that matches provider behavior. Record these properties\nbefore writing the provider call:\n\n| Contract area | What to declare |\n\n| Side effects | Every applicable read, write, delete, send-message, financial, identity, medical, legal, external-network, or code-execution effect |\n| Idempotency | Whether a key is required, its scope, duplicate behavior, and retention when known |\n| Execution | Supported completion modes, cancellation, retry, and retry safety |\n| Data | Sensitivity, retention, residency, and redaction behavior |\n| Credentials | Required handle and scopes without secret material |\n| Approval | Whether approval is required and what evidence is retained |\n| Transactions | Implemented plan, commit, reconciliation, and compensation modes |\n\nDo not infer a safe contract from the HTTP method. A provider may implement a\nPOST read, an asynchronous DELETE, or a write whose timeout leaves the\noutcome unknown.\n\nImplement CapabilityProviderConnector when callers or tests need the\ncapability list independently of the complete manifest. Return the same\ncapability definitions from both surfaces.\n\nMatch runtime support to the contract\n\nImplement FrozenConnector for the production execution boundary. Its\nimplementationsupport result is independent of the capability contract:\nthe contract says what the capability promises, while the support map says what\nthe current code implements.\n\nSet each support flag only when the corresponding path exists:\n• invocation for normal execution;\n• cancellation when cancellation reaches the provider operation;\n• streaming when incremental output reaches the runtime publisher;\n• retry when retry classification and downstream idempotency are enforced;\n• transaction for plan and commit;\n• reconciliation for unknown provider outcomes;\n• compensation for a separately governed compensation action;\n• approval for approval evidence and resume behavior;\n• credentials for deployment-resolved credential handles.\n\nThe discovery layer rejects claims such as streaming, cancellation, retry, or\ntransaction support when the implementation map does not support them. It also\nrejects a callable capability without an implementation claim when that\nadmission policy is enabled.\n\nEvery FrozenConnector operation receives ActionExecutionContext.\nAuthorize and scope the provider request from its authenticated actor, verified\ntenant, credential handle, deadline, cancellation token, idempotency reservation,\napproval evidence, transaction state, trace context, and redaction policy. Use\nthe supplied checkpoint and stream publishers for their declared purposes.\nDo not reconstruct authority from action input or metadata.\n\nThe host validates the signed gateway and the pinned route before it invokes the\nconnector. That host-level route check is not caller-controlled connector\nmetadata.\n\nThe frozen adapter rejects context-free execution. Keep that fail-closed\nbehavior; do not add a second path that calls the provider without trusted\ncontext.\n\nOperations that you do not implement already return\nconnector.operationunsupported. Override only the operations that the\nmanifest and support map advertise.\n\nMap provider failures conservatively\n\nReturn ConnectorFailure from typed operations. Preserve a stable namespaced\ncode, a redacted message, AIP error category, retry decision, optional retry\ndelay, provider request ID, durable provider operation reference, remote\nstatus, unknown-outcome flag, redacted details, source component, and connector\noperation.\n\nUse the point of failure to decide retry and reconciliation:\n\n| Observation | Safe connector decision |\n\n| Input rejected before dispatch | Permanent failure; no provider side effect |\n| Authentication or scope rejected | Non-retryable until credentials or policy change |\n| Provider rate limit on a retry-safe operation | Temporary and retryable with the provider delay when available |\n| Read failed before a response | Retry only when the capability contract permits it |\n| Mutation timed out after dispatch | Mark the outcome uncertain; do not report a safe blind retry |\n| Provider returned an operation ID | Retain it for status checks, cancellation, or reconciliation |\n| Cancellation won locally | Do not claim provider cancellation unless the remote endpoint confirmed it |\n| Response exceeded the configured bound | Fail closed and retain only redacted diagnostic data |\n\nNever place provider payloads, credentials, authorization headers, signing\nmaterial, or unbounded response bodies in message or\nredacteddetails.\n\nProtect secrets and provider destinations\n\nLoad credentials at the host boundary and wrap in ConnectorSecret.\nConnectorSecret is non-serializable, redacts its debug output, compares in\nconstant time, and zeroizes owned bytes on drop. Expose its bytes only while\nconstructing the downstream request.\n\nValidate provider destinations before accepting credentials:\n• require HTTPS outside an explicit trusted development boundary;\n• reject embedded usernames, passwords, fragments, and unexpected base paths;\n• construct paths from admitted operations instead of caller-supplied URLs;\n• allow only documented query keys, headers, redirects, and response types;\n• apply request, response, timeout, and concurrency bounds;\n• keep account or workspace identity in deployment configuration.\n\nUse an opaque credential handle or secret-provider reference in registry and\nroute state. A credential revision may be pinned to a route so an in-flight\naction cannot silently switch credentials during rotation.\n\nAdd ingress only when the provider needs it\n\nMount product routes with the common host only for authenticated provider\ningress. Verify the signature over the exact raw body before JSON\nnormalization. Validate the provider timestamp and account identity, reject\nreplayed nonces or event IDs through durable state, and bound the body before\nparsing it.\n\nPersist the accepted AIP event before acknowledging delivery when the provider\nretry contract requires durability. Publish to the central event endpoint\nthrough the host outbox so a transient central failure does not require a\nsecond provider delivery.\n\nIngress routes remain in the product host. They do not expand the central\ngetaip-server router or bypass the connector's tenant boundary.\n\nCompose the standalone host\n\nFlatten ConnectorHostBootstrapArgs into the product host CLI. Product\narguments add the provider origin, account identity, credential-file paths,\nenabled-operation configuration, and product limits.\n\nThe common bootstrap requires:\n• the public native endpoint and narrow control-plane endpoint;\n• admitted connector type, version, instance, and replica IDs;\n• tenant and membership identity;\n• gateway and control-plane verification DIDs;\n• the exact immutable artifact digest;\n• a durable PostgreSQL URL file and host signing-seed file;\n• a non-secret secret-provider reference;\n• topology, capacity, lease, heartbeat, drain, and health bounds.\n\nThe recurring host sequence is:\n1. read and validate product configuration and secrets;\n2. construct the connector;\n3. call PreparedConnectorHost::prepare;\n4. attach durable product stores or authenticated ingress;\n5. call serve, servewithrouter, or servewithrouterfactory;\n6. resolve shutdown through shutdownsignal.\n\nprepare validates deployment identity, discovers the manifest, configures\nsigning and trust, opens durable storage, and constructs the control-plane\nclient. Serving then recovers durable runtime state, registers the replica,\nrenews its lease, exposes the common HTTP surface, drains, and marks the\nreplica offline.\n\nThe common surface is:\n\n| Route | Meaning |\n\n| GET /health | Process and protocol identity only |\n| GET /ready | Lease, drain, durable storage, and connector readiness |\n| GET /metrics | Bounded connector-host metrics |\n| GET /aip/v1/manifest | Exact running manifest |\n| POST /aip/v1/messages | Signed, route-pinned native AIP execution |\n\nDo not use /health as a traffic gate. A host is ready only when /ready\nreturns success and the registry sees an eligible lease.\n\nPrepare immutable admission\n\nBuild the host as an immutable artifact and record its digest. Generate the\nmanifest and implementation support map from the same source and configuration\nclass. A production admission package binds:\n• connector type and immutable version;\n• manifest and canonical manifest digest;\n• artifact digest and SDK version requirement;\n• implementation support for every callable capability;\n• admission policies, tenant-owned instances, pre-provisioned replicas, and\n  tenant capability bindings;\n• seven mandatory evidence families.\n\nThe evidence families are OCI signature, SBOM, provenance, conformance,\nvulnerability policy, license policy, and revocation observation. Each evidence\nstatement binds the artifact digest, manifest digest, document digest, signer,\noutcome, issue time, and expiration. Deployment trust policy supplies separate\nroots for the package and each evidence role.\n\nUse the short-lived operator workflow after the release system has produced and\nsigned the package:\n\ngetaip connector registry plan \\\n  --package signed-admission.json \\\n  --trust-policy admission-trust-policy.json\n\ngetaip connector registry apply \\\n  --package signed-admission.json \\\n  --trust-policy admission-trust-policy.json \\\n  --database-url-file registry-database-url\n\nplan verifies signatures, evidence, time bounds, digests, SDK compatibility,\nmanifest invariants, and registry relationships without writing. apply\nuses a durable journal and can resume the same package revision and digest\nafter interruption. A changed digest under the same identity is a conflict, not\nan update.\n\nDo not give the long-running connector host registry-administrator credentials.\n\nTest the provider boundary\n\nUse layered tests so each result has a clear meaning:\n1. Unit-test identifiers, schemas, path construction, header construction,\n   redaction, response bounds, and failure mapping.\n2. Contract-test requests against a controlled provider stub. Include\n   idempotency collisions, reordered inputs, rate limits, timeouts, malformed\n   responses, and ambiguous mutation outcomes.\n3. Test webhook signatures, timestamps, replay fencing, account matching,\n   durable append, and central publication when ingress exists.\n4. Implement a ConnectorConformanceDriver and exercise every scenario\n   implied by the manifest and implementation support.\n5. Test host recovery, registration, lease loss, readiness, drain, offline\n   transition, credential rotation, and artifact mismatch.\n6. Run an isolated live-provider matrix only with an authorized test account and\n   retained evidence.\n\nThe frozen conformance model contains twelve scenario families. They cover\nidentity and credentials, schema enforcement, idempotency and duplicates, retry\nand exhaustion, cancellation races, streaming and backpressure, errors and\nuncertain outcomes, approval lifecycle, transaction lifecycle, audit and\nredaction, webhook security, and restart and reconnect.\n\nA scenario applies according to\nthe manifest and implementation support. An absent feature may make a scenario\nnot applicable; it must not be reported as a passed implementation.\n\nA source test demonstrates implementation behavior at that revision. Call a\nconnector qualified only when an exact artifact, topology, procedure, timestamp,\nand retained result satisfy the declared qualification scope.\n\nRoll out with a bounded first binding\n\nUse this order for the first deployment:\n1. Prepare a signed package with one non-production tenant binding and a\n   conservative admission policy, then verify it with plan.\n2. Apply that exact signed admission package.\n3. Deploy one replica with the exact admitted artifact digest and pre-provisioned\n   identity.\n4. Wait for durable recovery, successful registration, a valid lease, and\n   /ready.\n5. Compare the running manifest with the admitted manifest digest.\n6. Discover the bound capability through the product-neutral gateway.\n7. Invoke a read-only or otherwise non-destructive qualification capability.\n8. Observe errors, lease state, capacity, latency, and retained audit evidence.\n9. Expand bindings or replicas only after the bounded result is accepted.\n\nUse getaip connector test for a basic host manifest check:\n\nHOSTURL=https://connector.example.test\nCAPABILITYID=cap:twenty:metadata.list\n\ngetaip connector test \"$HOSTURL\" --capability \"$CAPABILITYID\"\n\nThe command confirms that the deployed endpoint advertises the requested\ncapability. It does not prove tenant routing, provider execution, or\nqualification. This example deliberately omits --invoke-capability: a\nstandalone host accepts signed actions only from its configured central gateway.\nPerform action qualification through that authorized route with an input and\nside-effect boundary approved for the test environment.\n\nVerify the completed connector\n\nBefore requesting catalog publication, confirm all of the following:\n• connector and host packages are separate and registered in the workspace;\n• the provider boundary and upstream revision are fixed;\n• manifest schemas and contracts match provider behavior;\n• implementation support matches every advertised feature;\n• typed execution uses trusted context and fails closed without it;\n• failure, retry, cancellation, and uncertain-outcome behavior is tested;\n• secrets stay in the host boundary and diagnostics remain redacted;\n• ingress is authenticated, replay-fenced, bounded, and durable when present;\n• the evidence and package reference the same artifact and manifest digests;\n• registry identities and the running replica match the admitted IDs;\n• the declared conformance and qualification scopes have retained results;\n• rollback has been rehearsed without discarding durable reconciliation state.\n\nRecord source revision, provider revision, artifact digest, manifest digest,\nadmission package ID and revision, tenant binding revision, test topology,\ntimestamps, and evidence locations.\n\nDecide failures without widening risk\n\n| Failure | Decision |\n\n| Manifest admission fails | Correct the manifest or implementation support; do not weaken policy to publish it |\n| Evidence is missing, stale, or mismatched | Rebuild the affected evidence for the exact artifact and manifest |\n| Host registers with a different ID or digest | Stop the replica and correct deployment identity |\n| /health succeeds but /ready fails | Inspect lease, drain, storage, and connector readiness before routing |\n| Provider authentication fails | Disable the binding or drain the replica before rotating credentials |\n| Mutation outcome is unknown | Preserve state and reconcile; do not send an unbounded retry |\n| Lease renewal becomes ambiguous | Let the host replay its fenced request; do not create an untracked replica |\n| Live-provider behavior differs from the contract | Disable the affected binding and reopen implementation review |\n\nRoll back without losing evidence\n\nStop new assignments by disabling the affected tenant binding or revoking the\napplied package revision. Drain the host before termination so assigned actions\ncan finish within the configured deadline and the registry can record the\noffline transition.\n\nRetain the connector runtime database, provider operation references,\nidempotency records, admission journal, signed package, evidence, logs, and\nmetrics needed to resolve uncertain outcomes. Do not replace the artifact under\nan existing immutable version ID. Admit a corrected version and move bindings\nthrough a separately reviewed rollout.\n\nRelated documentation\n• Capabilities (../concepts/capabilities.md)\n• Profiles and connectors (../concepts/profiles-and-connectors.md)\n• Identity and trust (../concepts/identity-and-trust.md)\n• Trusted local modules (trusted-local-modules.md)\n"
  },
  "integrity": {
    "algorithm": "sha256",
    "sourceDigest": "9cc117d384ecf83901f697a9987e42b557ba6c674dc96e9433bf03e417319ac0"
  }
}
