API: Connectors
Capability state: every operation in this file is
staging-durable(sandbox/fixture-only). Connector consent, sandbox-external evidence ingest, and connector status are recorded in durable M7 state but refuse production admission and reject raw connector payloads or credential secrets at the membrane. See 022 gap report item 11 for the broader connector surface.
The connector cluster covers the sandbox connector ingress surface — the operations that record connector consent, ingest hash-only redacted witnesses, and inspect connector status without exposing raw payloads, credential secrets, or biometric material.
Three coupled lanes:
- Consent lane —
evidence.connector.consentrecords sandbox connector consent, an adapter profile reference, scope, and a credential commitment, with no credential secret ingress. - Ingestion lane —
evidence.connector.ingestadmits fixture orsandbox_externalredacted witness material tied to a consented low-risk adapter profile (and optionally to a connector consent ref). - Status lane —
evidence.connector.statusreturns redacted summaries (ref counts, no payload bytes) for the current tenant.
The contract names these operations
evidence.connector.consent, evidence.connector.ingest, and
evidence.connector.status (i.e. they live under the
evidence.connector.* family). The TypeScript SDK exposes them
as connectorConsent, connectorEvidenceIngest, and
connectorEvidenceStatus.
A connector consent or witness never creates standing or authority on its own — see standing-and-mandates.md and authority.md for those surfaces.
See also:
- evidence.md — the broader witness surface,
including a worked
evidence.connector.ingestexample. - Guide: connector evidence.
evidence.connector.consent
Section titled “evidence.connector.consent”Record sandbox connector consent scope, hash-only adapter profile, and credential reference without credential secret ingress.
POST /v1/evidence/connectors/consentstate: staging-durablesdk_role: record sandbox connector consent scope, hash-only adapter profile, and credential reference without credential secret ingressrequest_record: CloudConnectorConsentRequestresponses: connector_consent | connector_witness | connector_adapter_profile | refusal | receiptRequest
Section titled “Request”interface ConnectorConsentRequest { tenant: GestaltRef; subject: GestaltRef; connector_kind: string; connector_mode: string; // must be "sandbox_external" source_system: string; source_label: string; consent_ref?: GestaltRef; credential_ref?: GestaltRef; adapter_id?: GestaltRef; adapter_version?: string; adapter_manifest_hash?: string; scopes: string[]; fixture: boolean; // must be true contains_customer_data: boolean; // refused if true raw_credential_material?: unknown; // refused if present}Response
Section titled “Response”{ "operation": "evidence.connector.consent", "outcome": "admitted", "body": { "connector_consent": "connector_consent:...", "connector_witness": "connector_witness:...", "adapter_profile": {...}, "credential_ref": "connector_credential:...", "status": "active", "credential_secret_stored": false, "raw_connector_payload_stored": false, "production_admission": false, "durable_state": {...} }, "receipt": {...}}The handler refuses with connector_mode_unsupported if
connector_mode is not "sandbox_external",
customer_data_forbidden if contains_customer_data is true,
and connector_credential_material_refused if
raw_credential_material is supplied.
SDK example
Section titled “SDK example”const consent = await client.connectorConsent({ tenant: "tenant_node:rheinwerk_calibration", subject: "company_geist:rheinwerk_calibration", connector_kind: "invoice", connector_mode: "sandbox_external", source_system: "sandbox_payment_feed", source_label: "sandbox://payments/m26", credential_ref: "connector_credential:m26_sandbox_reference", scopes: ["read:payments", "read:invoices"], fixture: true, contains_customer_data: false,});evidence.connector.ingest
Section titled “evidence.connector.ingest”Submit fixture or sandbox hash-only connector evidence as redacted witness material tied to a consented low-risk adapter profile.
A worked example with refusal codes and the
observed_input → transform_receipt → evidence_bundle pipeline
is documented in evidence.md.
POST /v1/evidence/connectors/ingeststate: staging-durablesdk_role: submit fixture or sandbox hash-only connector evidence as redacted witness material tied to a consented low-risk adapter profilerequest_record: CloudConnectorEvidenceIngestRequestresponses: connector_witness | observed_input | transform_receipt | evidence_bundle | connector_adapter_profile | refusal | receiptRequest
Section titled “Request”interface ConnectorEvidenceIngestRequest { tenant: GestaltRef; subject: GestaltRef; kind: string; connector_mode: string; // "fixture" or "sandbox_external" connector_consent?: GestaltRef; credential_ref?: GestaltRef; adapter_id?: GestaltRef; adapter_version?: string; adapter_manifest_hash?: string; idempotency_key?: string; source_system: string; source_label: string; source_hash?: string; transform_hash?: string; raw_kind: string; claims: string[]; amount_cents?: number; currency?: string; invoice?: GestaltRef; human_presence_receipt?: GestaltRef; face_match_receipt?: GestaltRef; advisor_decision?: string; stale: boolean; outside_tenant: boolean; fixture: boolean; contains_customer_data: boolean; raw_payload?: unknown; // refused if present raw_credential_material?: unknown; // refused if present}Response
Section titled “Response”See the worked example in
evidence.md. Body keys
include connector_witness, observed_input,
transform_receipt, evidence_bundle, and assertions that
raw_connector_payload_exposed, evidence_creates_authority,
and production_admission are all false.
SDK example
Section titled “SDK example”const ingested = await client.connectorEvidenceIngest({ tenant: "tenant_node:rheinwerk_calibration", subject: "company_geist:rheinwerk_calibration", kind: "invoice", connector_mode: "fixture", source_system: "fixture_connector", source_label: "fixtures/connectors/m9-invoice.json", raw_kind: "fixture_json", claims: ["invoice_payload"], amount_cents: 11900, currency: "EUR", stale: false, outside_tenant: false, fixture: true, contains_customer_data: false,});evidence.connector.revoke
Section titled “evidence.connector.revoke”Record connector revocation so future sandbox ingestion refuses with a stable code.
POST /v1/evidence/connectors/revokestate: staging-durablesdk_role: record connector revocation so future sandbox ingestion refuses with a stable coderequest_record: CloudConnectorRevokeRequestresponses: connector_revocation | refusal | receiptRequest
Section titled “Request”interface ConnectorRevokeRequest { tenant?: GestaltRef; connector_witness: GestaltRef; connector_consent?: GestaltRef; reason?: string; fixture?: boolean; // must be true today}fixture: true is required today. The membrane refuses with
connector_mode_unsupported for any non-fixture revocation.
Response
Section titled “Response”{ "operation": "evidence.connector.revoke", "outcome": "admitted", "body": { "connector_revocation": "connector_revocation:...", "connector_witness": "connector_witness:...", "status": "revoked", "future_ingest_refuses": true, "raw_connector_payload_stored": false, "production_admission": false, "durable_state": {...} }, "receipt": {...}}After revocation, future evidence.connector.ingest calls
referencing the revoked connector_witness fail closed.
SDK example
Section titled “SDK example”const revoked = await client.connectorRevoke({ tenant: "tenant_node:rheinwerk_calibration", connector_witness: "connector_witness:m26_sandbox_payment_feed", reason: "operator_revoked", fixture: true,});evidence.connector.status
Section titled “evidence.connector.status”Inspect redacted connector evidence summaries without raw
payload access. This operation is GET and takes no request
body.
GET /v1/evidence/connectors/statusstate: staging-durablesdk_role: inspect redacted connector evidence summaries without raw payload accessresponses: connector_witnesses | observed_inputs | transform_receipts | evidence_bundles | receiptRequest
Section titled “Request”No request body. Tenant scope is resolved from the caller’s authority context.
Response
Section titled “Response”{ "operation": "evidence.connector.status", "outcome": "verified", "body": { "tenant": "tenant_node:rheinwerk_calibration", "local_overlay": { "connector_consents": [...], "connector_revocations": [...], "connector_witnesses": [...], "observed_inputs": [...], "transform_receipts": [...], "evidence_bundles": [...], "evidence_reviews": [...] }, "remote_records": [...], "raw_connector_payload_exposed": false, "raw_db_exposed": false, "production_admission": false }, "receipt": {...}}Counts and refs only — raw payload bytes are never returned.
SDK example
Section titled “SDK example”const status = await client.connectorEvidenceStatus();Refusal codes
Section titled “Refusal codes”Selected refusal codes returned by this cluster (see
refusal.codes for the full list):
connector_fixture_onlyconnector_mode_unsupportedconnector_credential_material_refusedconnector_raw_payload_refusedconnector_tenant_scope_mismatchconnector_idempotency_collisionconnector_evidence_kind_unknowncustomer_data_forbiddenevidence_stalehuman_presence_creates_standing_refusedidentity_fallback_creates_standing_refusedWhere to read next
Section titled “Where to read next”- API: evidence —
evidence.witness.fixture, workedevidence.connector.ingestexample, theobserved_input → transform_receipt → evidence_bundlepipeline. - Guide: connector evidence.
- Reference: refusal codes.