Skip to content
Connections and credentials

Connections and credentials

A connection in FACE is made of two things that are stored apart: a record, which holds settings, and a credential bundle, which holds secrets. This page explains how they are split, stored and replicated, and what the connection RPCs report.

The connection record

Connection (in face.proto) carries:

FieldMeaning
idServer-generated when empty (conn_<nanoseconds>).
nameDisplay name. It is never used to decide how a connection behaves.
typeThe connector type, for example snowflake or mqtt. Matching ignores case, spaces, underscores and hyphens.
environmentFree-form tier label (prod, uat, …). It is not a statement about what stands behind the source.
runnerWhich runner executes work for this connection. See Runners.
configA oneof holding one typed configuration message, for example snowflake, mqtt or logistics_api.
propertiesA map<string,string> of extra non-secret settings. Many connectors read fallbacks from it.
credential_stateFilled by ListConnections (see below).
source_backingFilled by ListConnections (see below).

Secrets never stay on the record

Several configuration messages still have secret-looking fields (password, client_secret, personal_access_token, service_account_json, api_key, security_token). When a connection is created, FACE reads those fields, moves them into the credential bundle, and never writes them back out. A connection you read back through ListConnections has those fields empty. That is by design.

FACE flattens every setting to its catalogue name and decides secrecy by name, not by a hand-maintained list. A name is secret if its normalised form contains any of these markers: password, passwd, passphrase, secret, token, credential, privatekey, apikey, accesskey, accountkey, serviceaccountjson, connectionstring, signature, authorization, bearer. The internal record type has no field that can hold a secret. The same rule rejects secrets placed in the free-form properties map.

Connectors read their secrets only from the credential bundle they are handed. Setting a password on the record has no effect.

Connection strings

For snowflake and databricks you can paste a connection string in the connection_string property. FACE parses it at save time:

  • The settings it names become typed settings. The string wins for every setting it states. Settings it does not state keep what the form carried.
  • The secret it contains goes to the credential bundle under the connector’s normal key. The raw string itself is not kept.
  • If the string cannot be parsed, the save fails, so you find out when you paste, not at the next fetch.
  • For Snowflake, a DSN field that FACE does not carry is refused rather than dropped silently. So is an explicit host that disagrees with the account.

For other types, a connection_string credential is left in the bundle untouched. The Azure object store reads it from there.

Creating, listing and deleting

Create. CreateConnection takes the Connection and a credentials map. FACE writes the credential bundle first and then the record. If writing the credentials fails, no connection is created, and the response carries success: false with the underlying message. The response echoes connection_id either way, so a retry does not create a second row.

List. ListConnections returns every connection with two annotations and a warnings list:

  • credential_state tells you what this node holds:

    ValueMeaning
    CREDENTIAL_STATE_PRESENTA bundle was found and opened on this node. Nothing was dialled, so an expired password still reads PRESENT.
    CREDENTIAL_STATE_NONE_NEEDEDThe catalogue says this type reads no secret, for example Excel. This is a normal state.
    CREDENTIAL_STATE_ABSENTThere is no bundle for a type that expects one. FACE cannot tell “never entered” apart from “not present on this node”.
    CREDENTIAL_STATE_UNREADABLEA bundle exists and could not be opened. Re-entering the credential does not fix a key problem.
    CREDENTIAL_STATE_UNSPECIFIEDNot computed. This value is not “present” or “absent”.

    The fetch pipeline uses the same classifier, so the list and a fetch always agree. Opening a present bundle is recorded in the credential audit trail.

  • source_backing is covered below.

  • warnings carries plain-language conditions about the list itself, such as storage durability. Show them as written. They are not failures.

Delete. DeleteConnection answers with an explicit outcome:

outcomeMeaning
DELETE_CONNECTION_OUTCOME_DELETEDThe credential bundle was removed first, then the record.
DELETE_CONNECTION_OUTCOME_NOT_FOUNDThis instance holds no such id. Nothing was deleted.
DELETE_CONNECTION_OUTCOME_FAILEDThe delete was attempted and failed. message carries the error, and the connection may still exist. An empty id also returns this, with no connection id provided.

success is true only for DELETED. Deleting a connection does not revoke the credential at its issuer, and it does not rewrite fetch definitions or lineage that reference the id.

Test: what live_check_performed means

ConfigService.TestConnection resolves the connector for the connection’s type:

  • If the connector has a live probe, FACE runs it with the stored credentials.
  • If the connector has no live probe, FACE says so and does not claim a result.

Always read the two booleans together, never the message text:

successlive_check_performedMeaningTypical message
truetrueThe connector dialled the source, and the source answered and accepted the credential.Connectivity verified
truefalseThe configuration is stored. Nothing was verified. The type has no live probe.Configuration saved — a live connectivity check isn't implemented yet for this source type
falsetrueThe probe ran and failed. message is the connector’s own error.varies (see Troubleshooting)
falsefalseThe connection could not be resolved.Connection not found, Unknown connection type "…", could not read the connection: …

A successful probe establishes reachability and credential acceptance, and nothing more. It does not establish any of the following:

  • that a sensor is publishing
  • that an antenna is attached
  • that a probe is calibrated
  • that the credential has scope for any other resource
  • that any records exist

Each connector page lists exactly what its probe does.

Source backing

source_backing states what stands behind a connection on this instance. It is computed from the connection’s address and dials nothing.

ValueMeaningWhat it does not establish
SOURCE_BACKING_LIVENothing that FACE ships stands in for this connection. Whatever it addresses is what it reads.That the source exists, is reachable, or works. A connection to a host that does not exist is still LIVE and simply fails.
SOURCE_BACKING_MOCK_SERVICEThe address on the record is a service declared by the FACE demonstration estate, which is a stand-in and never a customer system.That the demonstration estate is deployed, reachable or serving. It is not deployed by default.
SOURCE_BACKING_MOCK_SEED_FILEDefined in the protocol for compatibility. Current servers never return it.—
SOURCE_BACKING_UNSPECIFIEDNot computed. Every RPC other than ListConnections leaves it unset.It is neither “live” nor “mock”.

When a connector fails, the failure is reported as a failure. No variant of FACE substitutes bundled sample rows for a failed source. environment is not a substitute for this field, because a customer may call one of their own systems “demo”.

Storage and replication

  • Records are one replicated snapshot per tenant. FACE stores the snapshot in its own encrypted application filesystem and proposes changes through the platform’s consensus group, so every control-plane replica sees the same set of connections.
  • Credential bundles are rows in the same encrypted store. Each row is sealed under a key derived for FACE and bound to its path. Bundles do not travel on the replication log. Only the record snapshot does.
  • When a fetch runs on a dedicated runner, the control plane reads the bundle once (an audited read). It then seals the bundle to that runner’s in-memory key for that single dispatch. The runner never writes the credential to disk. See Runners.

For the encryption and key model, see /docs/security/.

Observed lineage

Every connector returned by the registry is wrapped by a lineage recorder. Each extraction appends a record to an append-only log. The record contains:

  • column names
  • counts and durations
  • a literal-free query shape and its fingerprint
  • a closed-set error class

A record never contains result values, driver messages or credentials. Camera ingests are recorded separately (one record per ingest, with a row count of zero, because a camera sends frames rather than rows). Lineage is visible in source activity. See /docs/analysis/.