{
  "schemaVersion": "1.0",
  "title": "Qualify the Twenty connector",
  "description": "Use this procedure to evaluate one exact Twenty connector deployment. The result applies only to the recorded artifact, manifest, provider revision, workspace, credentials, configuration, topology, and executed cases.",
  "canonical": "https://getaip.org/docs/connectors/twenty/qualification",
  "route": "/docs/connectors/twenty/qualification",
  "source": "docs/connectors/twenty/qualification/README.md",
  "protocol": "Agent Interoperability Protocol",
  "protocolVersion": "1.0",
  "section": "Connectors",
  "documentType": "Connector",
  "language": "en",
  "downloads": {
    "md": "/docs/download/connectors/twenty/qualification.md",
    "txt": "/docs/download/connectors/twenty/qualification.txt",
    "json": "/docs/download/connectors/twenty/qualification.json",
    "pdf": "/docs/download/connectors/twenty/qualification.pdf"
  },
  "content": {
    "format": "text/markdown",
    "markdown": "---\ntitle: Qualify the Twenty connector\ndescription: >-\n  Qualify one exact Twenty connector artifact through source, supply-chain,\n  workspace, operation, webhook, failure, recovery, and evidence gates\nkind: qualification\naudience: integrator\nappliesTo: \"1.x\"\nwritingStandard: \"aip-docs/1.0\"\nlastReviewedRevision: \"97be86e9efedf07ecf1783b03800f683f107fb04\"\nconnector: twenty\naliases:\n  - Twenty connector qualification\n  - Twenty connector evidence\n  - Qualify aip-host-twenty\n---\n\n# Qualify the Twenty connector\n\nUse this procedure to evaluate one exact Twenty connector deployment. The\nresult applies only to the recorded artifact, manifest, provider revision,\nworkspace, credentials, configuration, topology, and executed cases.\n\nSource inspection, unit tests, image checks, and admission are separate gates.\nNone establishes provider behavior without retained execution evidence.\n\n## Define the qualification claim\n\nState one bounded claim before execution:\n\n> The identified Twenty connector artifact preserves AIP identity, workspace\n> isolation, governed CRM operations, mutation uncertainty, authenticated\n> webhook admission, replay fencing, and recovery for the executed cases.\n\nExclude unexecuted operations, arbitrary provider revisions, downstream\nautomation, provider exactly-once behavior, and release attestation. Record\nevery case as `PASS`, `FAIL`, or `NOT RUN`.\n\n## Freeze every identity\n\nRecord these values in the run manifest:\n\n| Identity | Required value |\n|---|---|\n| AIP source | Full commit, clean-tree digest, Cargo lock digest, and target architecture |\n| Host artifact | Immutable image digest, OCI labels, SBOM, provenance, signature, and binary version |\n| Connector manifest | Manifest digest, profile, 22-operation catalogue digest, and admitted subset |\n| Twenty mapping | Upstream revision `96a24563674313a3071d359bfccaf33d5e130ab8` |\n| Provider | Immutable image digest or hosted release identity and API compatibility record |\n| Workspace | Workspace UUID, external-account ID, tenant binding, and sanitized fixture identity |\n| Credentials | Non-secret token ID, revision, scope, issuer, expiry, and rotation policy |\n| Webhooks | HMAC-secret revision, endpoint identity, replay scope, and event destination |\n| Fleet | Type, version, instance, replica, tenant, assignment, region, zone, and lease identity |\n| State | PostgreSQL identity, schema state, backup point, and retention policy |\n| Runner | Operating system, architecture, container engine, Rust, CLI, and clock source |\n| Time | Run ID, UTC start and completion, operator, and reviewer |\n\nUse immutable artifacts during execution. Any identity change creates a new\nqualification claim.\n\n## Prepare isolated fixtures and evidence\n\nUse a dedicated workspace containing synthetic records and metadata. Do not run\ndestructive cases against an ordinary CRM workspace.\n\nCreate an owner-controlled evidence directory:\n\n```text\ntwenty-qualification/<run-id>/\n├── identity/\n├── source-tests/\n├── images/\n├── admission/\n├── operations/\n├── webhooks/\n├── failures/\n├── recovery/\n├── cleanup/\n├── results.jsonl\n├── summary.json\n└── limitations.md\n```\n\nKeep secrets and unredacted CRM data outside the publishable bundle. Retain\ncryptographic digests and redacted evidence indexes instead.\n\n## Gate 1: verify source contracts\n\nAt the reviewed AIP revision, verify:\n\n- connector ID `twenty` and profile `aip.connector.twenty.v1` remain stable;\n- the upstream mapping revision is the frozen Forty-character commit above;\n- exactly 22 unique operations map to unique capability IDs;\n- eight reads are low risk and fourteen mutations require approval and idempotency;\n- the catalogue contains twenty tools and two resources;\n- provider routes remain fixed REST and metadata routes without a generic proxy;\n- request, response, workspace, object-name, UUID, query, and body guards remain active;\n- provider redirects remain disabled and Bearer authentication remains fixed;\n- webhook HMAC, clock, nonce, workspace, event, replay, and redaction checks remain active;\n- manifest and public capability assets match the implementation.\n\nFail this gate on source or generated-asset drift. Do not repair a mismatch by\nediting only a manifest or documentation asset.\n\n## Gate 2: run the connector tests\n\nThe package test gate is:\n\n```sh\ncargo test --locked -p aip-connector-twenty\n```\n\nRetain the exact command, environment, exit status, and complete output. Confirm\nthe eight source tests cover:\n\n1. complete, unique, governed capability projection;\n2. unsafe configuration and provider-identifier rejection;\n3. deterministic create identity and forced provider upsert;\n4. non-empty bulk filters and explicit permanent-delete mode;\n5. host-owned webhook secrets and recursive response redaction;\n6. signed webhook mapping and replay rejection;\n7. replay expiry pruning and capacity enforcement;\n8. mutation uncertainty during temporary provider failures.\n\nThese tests establish local mapping invariants. They do not contact a real\nTwenty provider or prove a built artifact.\n\n## Gate 3: verify the host image\n\nApply the source-owned product image policy to `aip-host-twenty`:\n\n| Check | Required result |\n|---|---|\n| Image identity | Immutable SHA-256 image ID and admitted digest agree |\n| Runtime user | `10001:10001` |\n| Entrypoint | `/usr/local/bin/aip-connector-host` |\n| Component label | `aip-host-twenty` |\n| Revision label | Exact AIP source identity |\n| Version label | Exact connector release version |\n| Runtime probe | Hardened read-only container returns `--help` successfully |\n| Supply chain | Inspect, full history, SPDX SBOM, signature, provenance, and policy decision retained |\n\nThe generic verifier builds and inspects the image. It does not start a Twenty\nworkspace or execute an AIP operation.\n\n## Gate 4: verify admission and workspace isolation\n\nRequire one verified admission package whose artifact and manifest digests match\nthe running replica. Confirm the admitted operation subset equals discovery.\n\nVerify all fleet identities in signed requests, registry state, host\nconfiguration, and responses. The provider workspace UUID must equal the\nintended external-account binding under deployment policy.\n\nUse two isolated tenants and workspaces for negative cases:\n\n| Case | Required result |\n|---|---|\n| Authorized tenant and workspace | Discovery and bounded read succeed through the admitted replica |\n| Authorized tenant, wrong external account | No eligible route or provider dispatch |\n| Unauthorized tenant | No discovery result and no eligible route |\n| Valid token, wrong configured workspace | Qualification fails before any claim of isolation |\n| Cross-workspace record ID | No data disclosure or mutation outside the bound workspace |\n\nPreserve registry, gateway, host, and provider evidence for each negative case.\n\n## Gate 5: exercise all 22 operations\n\nExecute every admitted operation against synthetic fixtures. Record request,\napproval, provider dispatch, result, verification read, cleanup, and failure\nstate for each mutation.\n\n| Family | Operations requiring individual evidence |\n|---|---|\n| Query | `record.list`, `record.get`, `record.find_duplicates`, `record.group_by` |\n| Create and update | `record.create`, `record.create_many`, `record.update`, `record.update_many` |\n| Delete and merge | `record.soft_delete`, `record.soft_delete_many`, `record.destroy`, `record.destroy_many`, `record.restore`, `record.restore_many`, `record.merge` |\n| Metadata | `metadata.list`, `metadata.get`, `metadata.create`, `metadata.update`, `metadata.delete` |\n| OpenAPI | `openapi.core`, `openapi.metadata` |\n\nFor reads, verify bounds, filters, pagination, object identity, workspace, and\nredaction. For mutations, verify before and after state without assuming that\nan AIP terminal result proves every downstream effect.\n\n## Gate 6: verify governance and idempotency\n\nFor each of the fourteen mutations, retain:\n\n- immutable Action and capability identity;\n- canonical input hash and idempotency-key digest;\n- approval request, decision, policy hash, and evidence references;\n- provider request identity when supplied;\n- terminal AIP result or structured error;\n- verification read and cleanup result.\n\nReplay the same Action and key with identical input. Require one governed intent\nand one stable result. Change the input under the same key and require collision\nrejection before provider dispatch.\n\nFor `record.create`, `record.create_many`, and `record.update`, verify the\ndocumented safe-with-key path. Treat every other mutation as unsafe to retry.\n\nInterrupt provider responses after possible commit. Require uncertain mutation\nclassification and provider-state reconciliation without a replacement Action\nor key.\n\n## Gate 7: verify mutation safeguards\n\nRun bounded negative cases for:\n\n- missing approval or idempotency key;\n- empty, absent, `null`, or `{}` bulk filters;\n- permanent-delete requests without explicit permanent mode;\n- malformed object names and record UUIDs;\n- oversized request and response bodies;\n- invalid metadata resource and query combinations;\n- supplied webhook secret in metadata input;\n- unsupported page-layout field combinations;\n- direct provider GraphQL or arbitrary-route attempts.\n\nRequire rejection before provider dispatch when the connector owns the guard.\nRetain provider evidence when enforcement belongs to Twenty.\n\n## Gate 8: verify webhook security and delivery\n\nEnable webhook ingress only with shared durable replay state. Exercise these\ncases with the exact raw request body:\n\n| Case | Required result |\n|---|---|\n| Valid delivery | HMAC accepted, deterministic event created, and central outcome recorded |\n| Same nonce replay | Rejected without a second event |\n| Forged signature | Rejected without replay or event persistence |\n| Timestamp outside five minutes | Rejected |\n| Wrong workspace UUID | Rejected |\n| Missing required header | Rejected before connector admission |\n| Body above four MiB | Rejected |\n| Replay store unavailable | Fail closed without accepting the nonce as complete |\n| Central endpoint unavailable | Local durable outbox owns exactly one accepted event |\n\nConfirm replay capacity at 100,000 live nonces and verify expiry pruning. Run a\nconcurrent same-nonce race across every replica of one logical instance.\n\n## Gate 9: verify errors, limits, and redaction\n\nExercise provider `401`, `403`, `429`, ordinary `4xx`, `5xx`, connection\nfailure, post-dispatch transport failure, invalid JSON, and oversized response.\n\nVerify the exact connector error class, retry flag, retry delay, remote status,\nprovider request ID, uncertainty flag, source component, and operation. Confirm\nthat returned provider details use the bounded allowlist.\n\nInspect logs, traces, AIP errors, events, and retained files for API tokens,\nwebhook secrets, signing seeds, raw idempotency keys, raw HMAC material, and\nunapproved CRM data. Any secret disclosure fails qualification.\n\n## Gate 10: verify restart and fleet behavior\n\nExecute each fault with before, fault, after, and recovery evidence:\n\n| Fault | Required result |\n|---|---|\n| Graceful host restart | Same instance state returns ready and prior results remain readable |\n| Host termination during read | Route fails closed and bounded retry follows read policy |\n| Host termination during mutation | Original Action remains fenced until provider state is reconciled |\n| PostgreSQL outage | Readiness fails and no stateful admission bypass occurs |\n| Registry lease expiry | Replica becomes ineligible and recovers with the same logical identity |\n| Credential rotation | Old revision stops authorizing and new revision requires policy agreement |\n| Provider outage | Readiness and operation errors preserve their distinct evidence |\n| Two host replicas | Shared Action, idempotency, replay, event, outbox, and lease state remain coherent |\n\nDo not replace PostgreSQL with empty state during recovery. Preserve the\noriginal Action, replay scope, event, outbox, instance, and replica evidence.\n\n## Inspect retained local evidence separately\n\nThe retained bundle inspected for this page records one historical local run\nwith these identities:\n\n| Field | Retained value |\n|---|---|\n| Scope | `local_e2e_qualification_not_release_attestation` |\n| AIP source | `workspace-sha256:43f82b2d60d04f08750d3c7bc0eb2564e53b6d20a5ad6de06d3ce5f618605fdc` |\n| Host artifact | `sha256:35e12b264ad28ee21150a77d8de6aaaf8b86d264822998b6465399564f492ff5` |\n| Manifest | `sha256:a23d7fdc41dfe1f729ea84971f1778d357d5fa7d0eff75e13aa18fb5cac8e495` |\n| Live evidence | `sha256:810714686150b4846936b2d1880ad5925585f15830fd5cec8930b9a9d02224ac` |\n| Twenty mapping | `96a24563674313a3071d359bfccaf33d5e130ab8` |\n| Admission plan | `verified` for the recorded artifact and version |\n\nIts native summary records 22 discovered capabilities, two reads, two governed\nmutations, two approval decisions, two durable result reads, two replays, one\ncreate, and one destroy as passed.\n\nIts webhook summary records one accepted signed delivery, one rejected replay,\none rejected forgery, and one observed central event as passed.\n\nThese summaries are retained historical evidence for their recorded workspace\ndigest and artifacts. They do not map that workspace digest to reviewed commit\n`97be86e9efedf07ecf1783b03800f683f107fb04` and do not cover all gates above.\n\nThe reviewed source-owned five-product Compose topology also has no Twenty\nruntime service. Current exact-artifact qualification therefore remains\nunestablished until a complete run seals matching identities and cases.\n\n## Inspect and seal the evidence bundle\n\nRequire these groups before deciding the result:\n\n- source revision, lockfile, dependency, runner, and clock identities;\n- image inspect, history, SBOM, signature, provenance, and policy decisions;\n- admission package, manifest, trust decision, and registry state;\n- tenant, workspace, credential, provider, and fixture identities;\n- test commands, outputs, exit codes, and per-case result ledger;\n- signed native requests, approvals, responses, and verification reads;\n- webhook requests, replay decisions, events, and outbox outcomes;\n- fault injection, readiness, lease, storage, and recovery timelines;\n- sanitized logs and explicit limitations;\n- cleanup evidence and a cryptographic manifest of every retained file.\n\nValidate that every indexed file exists. Keep restricted raw evidence separate\nfrom the publishable index.\n\n## Decide the result\n\n| Result | Rule |\n|---|---|\n| `PASS` | Every required gate passed for the frozen identities and every limitation is explicit |\n| `FAIL` | A required case failed, identity drifted, evidence conflicts, or a secret escaped |\n| `NOT RUN` | The case did not execute or lacks sufficient retained evidence |\n\nA bounded qualification may pass with explicit out-of-scope cases only when the\nclaim excludes them. Missing evidence never becomes a passing result.\n\nPublish artifact, manifest, provider, workspace, and topology identities with\nthe executed case list, evidence-manifest digest, result, and limitations. Do\nnot publish credentials or unredacted CRM content.\n\n## Clean up without losing proof\n\nAfter sealing the evidence bundle:\n\n1. remove synthetic records, metadata, views, layouts, and webhooks through governed cleanup;\n2. verify cleanup with bounded reads;\n3. revoke run-scoped credentials, assignments, and webhook secrets;\n4. stop only the isolated qualification topology;\n5. retain required state snapshots under evidence policy;\n6. verify evidence hashes after transfer;\n7. record cleanup status separately from the qualification result.\n\nCleanup failure is an operational failure. It does not rewrite the result of an\nalready executed case.\n\n## Related documentation\n\n- [Twenty connector overview](../README.md)\n- [Twenty capability index](../capabilities/README.md)\n- [Deploy the Twenty connector](../operations/deployment.md)\n- [Twenty health, observability, and recovery](../operations/health-observability-and-recovery.md)\n- [Conformance and qualification](../../../reference/conformance.md)\n",
    "text": "Qualify the Twenty connector\n\nUse this procedure to evaluate one exact Twenty connector deployment. The\nresult applies only to the recorded artifact, manifest, provider revision,\nworkspace, credentials, configuration, topology, and executed cases.\n\nSource inspection, unit tests, image checks, and admission are separate gates.\nNone establishes provider behavior without retained execution evidence.\n\nDefine the qualification claim\n\nState one bounded claim before execution:\n\nThe identified Twenty connector artifact preserves AIP identity, workspace\nisolation, governed CRM operations, mutation uncertainty, authenticated\nwebhook admission, replay fencing, and recovery for the executed cases.\n\nExclude unexecuted operations, arbitrary provider revisions, downstream\nautomation, provider exactly-once behavior, and release attestation. Record\nevery case as PASS, FAIL, or NOT RUN.\n\nFreeze every identity\n\nRecord these values in the run manifest:\n\n| Identity | Required value |\n\n| AIP source | Full commit, clean-tree digest, Cargo lock digest, and target architecture |\n| Host artifact | Immutable image digest, OCI labels, SBOM, provenance, signature, and binary version |\n| Connector manifest | Manifest digest, profile, 22-operation catalogue digest, and admitted subset |\n| Twenty mapping | Upstream revision 96a24563674313a3071d359bfccaf33d5e130ab8 |\n| Provider | Immutable image digest or hosted release identity and API compatibility record |\n| Workspace | Workspace UUID, external-account ID, tenant binding, and sanitized fixture identity |\n| Credentials | Non-secret token ID, revision, scope, issuer, expiry, and rotation policy |\n| Webhooks | HMAC-secret revision, endpoint identity, replay scope, and event destination |\n| Fleet | Type, version, instance, replica, tenant, assignment, region, zone, and lease identity |\n| State | PostgreSQL identity, schema state, backup point, and retention policy |\n| Runner | Operating system, architecture, container engine, Rust, CLI, and clock source |\n| Time | Run ID, UTC start and completion, operator, and reviewer |\n\nUse immutable artifacts during execution. Any identity change creates a new\nqualification claim.\n\nPrepare isolated fixtures and evidence\n\nUse a dedicated workspace containing synthetic records and metadata. Do not run\ndestructive cases against an ordinary CRM workspace.\n\nCreate an owner-controlled evidence directory:\n\ntwenty-qualification//\n├── identity/\n├── source-tests/\n├── images/\n├── admission/\n├── operations/\n├── webhooks/\n├── failures/\n├── recovery/\n├── cleanup/\n├── results.jsonl\n├── summary.json\n└── limitations.md\n\nKeep secrets and unredacted CRM data outside the publishable bundle. Retain\ncryptographic digests and redacted evidence indexes instead.\n\nGate 1: verify source contracts\n\nAt the reviewed AIP revision, verify:\n• connector ID twenty and profile aip.connector.twenty.v1 remain stable;\n• the upstream mapping revision is the frozen Forty-character commit above;\n• exactly 22 unique operations map to unique capability IDs;\n• eight reads are low risk and fourteen mutations require approval and idempotency;\n• the catalogue contains twenty tools and two resources;\n• provider routes remain fixed REST and metadata routes without a generic proxy;\n• request, response, workspace, object-name, UUID, query, and body guards remain active;\n• provider redirects remain disabled and Bearer authentication remains fixed;\n• webhook HMAC, clock, nonce, workspace, event, replay, and redaction checks remain active;\n• manifest and public capability assets match the implementation.\n\nFail this gate on source or generated-asset drift. Do not repair a mismatch by\nediting only a manifest or documentation asset.\n\nGate 2: run the connector tests\n\nThe package test gate is:\n\ncargo test --locked -p aip-connector-twenty\n\nRetain the exact command, environment, exit status, and complete output. Confirm\nthe eight source tests cover:\n1. complete, unique, governed capability projection;\n2. unsafe configuration and provider-identifier rejection;\n3. deterministic create identity and forced provider upsert;\n4. non-empty bulk filters and explicit permanent-delete mode;\n5. host-owned webhook secrets and recursive response redaction;\n6. signed webhook mapping and replay rejection;\n7. replay expiry pruning and capacity enforcement;\n8. mutation uncertainty during temporary provider failures.\n\nThese tests establish local mapping invariants. They do not contact a real\nTwenty provider or prove a built artifact.\n\nGate 3: verify the host image\n\nApply the source-owned product image policy to aip-host-twenty:\n\n| Check | Required result |\n\n| Image identity | Immutable SHA-256 image ID and admitted digest agree |\n| Runtime user | 10001:10001 |\n| Entrypoint | /usr/local/bin/aip-connector-host |\n| Component label | aip-host-twenty |\n| Revision label | Exact AIP source identity |\n| Version label | Exact connector release version |\n| Runtime probe | Hardened read-only container returns --help successfully |\n| Supply chain | Inspect, full history, SPDX SBOM, signature, provenance, and policy decision retained |\n\nThe generic verifier builds and inspects the image. It does not start a Twenty\nworkspace or execute an AIP operation.\n\nGate 4: verify admission and workspace isolation\n\nRequire one verified admission package whose artifact and manifest digests match\nthe running replica. Confirm the admitted operation subset equals discovery.\n\nVerify all fleet identities in signed requests, registry state, host\nconfiguration, and responses. The provider workspace UUID must equal the\nintended external-account binding under deployment policy.\n\nUse two isolated tenants and workspaces for negative cases:\n\n| Case | Required result |\n\n| Authorized tenant and workspace | Discovery and bounded read succeed through the admitted replica |\n| Authorized tenant, wrong external account | No eligible route or provider dispatch |\n| Unauthorized tenant | No discovery result and no eligible route |\n| Valid token, wrong configured workspace | Qualification fails before any claim of isolation |\n| Cross-workspace record ID | No data disclosure or mutation outside the bound workspace |\n\nPreserve registry, gateway, host, and provider evidence for each negative case.\n\nGate 5: exercise all 22 operations\n\nExecute every admitted operation against synthetic fixtures. Record request,\napproval, provider dispatch, result, verification read, cleanup, and failure\nstate for each mutation.\n\n| Family | Operations requiring individual evidence |\n\n| Query | record.list, record.get, record.findduplicates, record.groupby |\n| Create and update | record.create, record.createmany, record.update, record.updatemany |\n| Delete and merge | record.softdelete, record.softdeletemany, record.destroy, record.destroymany, record.restore, record.restoremany, record.merge |\n| Metadata | metadata.list, metadata.get, metadata.create, metadata.update, metadata.delete |\n| OpenAPI | openapi.core, openapi.metadata |\n\nFor reads, verify bounds, filters, pagination, object identity, workspace, and\nredaction. For mutations, verify before and after state without assuming that\nan AIP terminal result proves every downstream effect.\n\nGate 6: verify governance and idempotency\n\nFor each of the fourteen mutations, retain:\n• immutable Action and capability identity;\n• canonical input hash and idempotency-key digest;\n• approval request, decision, policy hash, and evidence references;\n• provider request identity when supplied;\n• terminal AIP result or structured error;\n• verification read and cleanup result.\n\nReplay the same Action and key with identical input. Require one governed intent\nand one stable result. Change the input under the same key and require collision\nrejection before provider dispatch.\n\nFor record.create, record.createmany, and record.update, verify the\ndocumented safe-with-key path. Treat every other mutation as unsafe to retry.\n\nInterrupt provider responses after possible commit. Require uncertain mutation\nclassification and provider-state reconciliation without a replacement Action\nor key.\n\nGate 7: verify mutation safeguards\n\nRun bounded negative cases for:\n• missing approval or idempotency key;\n• empty, absent, null, or {} bulk filters;\n• permanent-delete requests without explicit permanent mode;\n• malformed object names and record UUIDs;\n• oversized request and response bodies;\n• invalid metadata resource and query combinations;\n• supplied webhook secret in metadata input;\n• unsupported page-layout field combinations;\n• direct provider GraphQL or arbitrary-route attempts.\n\nRequire rejection before provider dispatch when the connector owns the guard.\nRetain provider evidence when enforcement belongs to Twenty.\n\nGate 8: verify webhook security and delivery\n\nEnable webhook ingress only with shared durable replay state. Exercise these\ncases with the exact raw request body:\n\n| Case | Required result |\n\n| Valid delivery | HMAC accepted, deterministic event created, and central outcome recorded |\n| Same nonce replay | Rejected without a second event |\n| Forged signature | Rejected without replay or event persistence |\n| Timestamp outside five minutes | Rejected |\n| Wrong workspace UUID | Rejected |\n| Missing required header | Rejected before connector admission |\n| Body above four MiB | Rejected |\n| Replay store unavailable | Fail closed without accepting the nonce as complete |\n| Central endpoint unavailable | Local durable outbox owns exactly one accepted event |\n\nConfirm replay capacity at 100,000 live nonces and verify expiry pruning. Run a\nconcurrent same-nonce race across every replica of one logical instance.\n\nGate 9: verify errors, limits, and redaction\n\nExercise provider 401, 403, 429, ordinary 4xx, 5xx, connection\nfailure, post-dispatch transport failure, invalid JSON, and oversized response.\n\nVerify the exact connector error class, retry flag, retry delay, remote status,\nprovider request ID, uncertainty flag, source component, and operation. Confirm\nthat returned provider details use the bounded allowlist.\n\nInspect logs, traces, AIP errors, events, and retained files for API tokens,\nwebhook secrets, signing seeds, raw idempotency keys, raw HMAC material, and\nunapproved CRM data. Any secret disclosure fails qualification.\n\nGate 10: verify restart and fleet behavior\n\nExecute each fault with before, fault, after, and recovery evidence:\n\n| Fault | Required result |\n\n| Graceful host restart | Same instance state returns ready and prior results remain readable |\n| Host termination during read | Route fails closed and bounded retry follows read policy |\n| Host termination during mutation | Original Action remains fenced until provider state is reconciled |\n| PostgreSQL outage | Readiness fails and no stateful admission bypass occurs |\n| Registry lease expiry | Replica becomes ineligible and recovers with the same logical identity |\n| Credential rotation | Old revision stops authorizing and new revision requires policy agreement |\n| Provider outage | Readiness and operation errors preserve their distinct evidence |\n| Two host replicas | Shared Action, idempotency, replay, event, outbox, and lease state remain coherent |\n\nDo not replace PostgreSQL with empty state during recovery. Preserve the\noriginal Action, replay scope, event, outbox, instance, and replica evidence.\n\nInspect retained local evidence separately\n\nThe retained bundle inspected for this page records one historical local run\nwith these identities:\n\n| Field | Retained value |\n\n| Scope | locale2equalificationnotreleaseattestation |\n| AIP source | workspace-sha256:43f82b2d60d04f08750d3c7bc0eb2564e53b6d20a5ad6de06d3ce5f618605fdc |\n| Host artifact | sha256:35e12b264ad28ee21150a77d8de6aaaf8b86d264822998b6465399564f492ff5 |\n| Manifest | sha256:a23d7fdc41dfe1f729ea84971f1778d357d5fa7d0eff75e13aa18fb5cac8e495 |\n| Live evidence | sha256:810714686150b4846936b2d1880ad5925585f15830fd5cec8930b9a9d02224ac |\n| Twenty mapping | 96a24563674313a3071d359bfccaf33d5e130ab8 |\n| Admission plan | verified for the recorded artifact and version |\n\nIts native summary records 22 discovered capabilities, two reads, two governed\nmutations, two approval decisions, two durable result reads, two replays, one\ncreate, and one destroy as passed.\n\nIts webhook summary records one accepted signed delivery, one rejected replay,\none rejected forgery, and one observed central event as passed.\n\nThese summaries are retained historical evidence for their recorded workspace\ndigest and artifacts. They do not map that workspace digest to reviewed commit\n97be86e9efedf07ecf1783b03800f683f107fb04 and do not cover all gates above.\n\nThe reviewed source-owned five-product Compose topology also has no Twenty\nruntime service. Current exact-artifact qualification therefore remains\nunestablished until a complete run seals matching identities and cases.\n\nInspect and seal the evidence bundle\n\nRequire these groups before deciding the result:\n• source revision, lockfile, dependency, runner, and clock identities;\n• image inspect, history, SBOM, signature, provenance, and policy decisions;\n• admission package, manifest, trust decision, and registry state;\n• tenant, workspace, credential, provider, and fixture identities;\n• test commands, outputs, exit codes, and per-case result ledger;\n• signed native requests, approvals, responses, and verification reads;\n• webhook requests, replay decisions, events, and outbox outcomes;\n• fault injection, readiness, lease, storage, and recovery timelines;\n• sanitized logs and explicit limitations;\n• cleanup evidence and a cryptographic manifest of every retained file.\n\nValidate that every indexed file exists. Keep restricted raw evidence separate\nfrom the publishable index.\n\nDecide the result\n\n| Result | Rule |\n\n| PASS | Every required gate passed for the frozen identities and every limitation is explicit |\n| FAIL | A required case failed, identity drifted, evidence conflicts, or a secret escaped |\n| NOT RUN | The case did not execute or lacks sufficient retained evidence |\n\nA bounded qualification may pass with explicit out-of-scope cases only when the\nclaim excludes them. Missing evidence never becomes a passing result.\n\nPublish artifact, manifest, provider, workspace, and topology identities with\nthe executed case list, evidence-manifest digest, result, and limitations. Do\nnot publish credentials or unredacted CRM content.\n\nClean up without losing proof\n\nAfter sealing the evidence bundle:\n1. remove synthetic records, metadata, views, layouts, and webhooks through governed cleanup;\n2. verify cleanup with bounded reads;\n3. revoke run-scoped credentials, assignments, and webhook secrets;\n4. stop only the isolated qualification topology;\n5. retain required state snapshots under evidence policy;\n6. verify evidence hashes after transfer;\n7. record cleanup status separately from the qualification result.\n\nCleanup failure is an operational failure. It does not rewrite the result of an\nalready executed case.\n\nRelated documentation\n• Twenty connector overview (../README.md)\n• Twenty capability index (../capabilities/README.md)\n• Deploy the Twenty connector (../operations/deployment.md)\n• Twenty health, observability, and recovery (../operations/health-observability-and-recovery.md)\n• Conformance and qualification (../../../reference/conformance.md)\n"
  },
  "integrity": {
    "algorithm": "sha256",
    "sourceDigest": "cd8435b2de3909174e5363ff6ef670a46bd067cd06d87460a10a45aa0b5d2eee"
  }
}
