Skip to content

Configuration reference

Use this page to find profile behavior, ECNConfig fields and defaults, and authentication-source mapping.

picogrid-ecn configure writes a versioned profile file to the platform configuration directory. $XDG_CONFIG_HOME, when set, takes precedence on supported POSIX platforms:

  • XDG: $XDG_CONFIG_HOME/picogrid/ecn-sdk/profiles.json;
  • Linux fallback: ~/.config/picogrid/ecn-sdk/profiles.json;
  • macOS: ~/Library/Application Support/picogrid/ecn-sdk/profiles.json.

Named-profile persistence is currently supported on POSIX systems where the SDK can enforce ownership-safe directory operations and modes. On Windows, use environment variables or construct ECNConfig directly until an equivalent fail-closed storage implementation is verified.

The SDK-owned directory is mode 0700 and the file is mode 0600. Writes are atomic. Symlinks, unsafe modes, duplicate JSON keys, and unsupported profile versions fail closed.

The file stores only endpoint settings, authentication kind, integration identity, reconnect policy, and credential-file references. It never stores bearer tokens, private-key passwords, refresh tokens, or client secrets. Load a profile through the public API:

from picogrid_ecn_client import load_config
config = load_config(profile="NAME")

Reviewed-container-network mode is not a named-profile authentication kind. It is available only through environment variables or direct ECNConfig construction, so the operator’s security attestation is never silently persisted to a profile file.

The named-profile authentication kinds and defaults are:

KindDefault portCredential source
mtls8883CA, client-certificate, and private-key file references
bearer8884Provided MQTT username plus a current token supplied at runtime
legion8884Current local legion-system-auth access token and integrationId

Override a default port only when Picogrid provided a different endpoint. Examples accept --profile NAME or ECN_PROFILE. Environment variables remain supported for CI and automation.

ECNConfig is immutable validated configuration for one SDK MQTT v5 connection. Fields are grouped by purpose for faster lookup.

FieldDefaultMeaning
hostrequiredDNS name or IP literal (IPv4 or IPv6) without scheme or port.
mqtt_portrequiredPort from 1 through 65535; profile loading defaults to 8883 for mTLS and 8884 for bearer or local legion-system-auth, while environment loading defaults to 1883 for none.
ntp_hostECN hostOptional issued alternate endpoint for the ECN-relative clock diagnostic.
ntp_port123UDP port from 1 through 65535 for the ECN-relative clock diagnostic.
integration_namerequired2-128 ASCII letters, digits, _, or -; starts and ends alphanumeric; geolocation and response are reserved case-insensitively. Also the client-ID prefix and offline mock bearer username.
terminal_idNoneCanonical UUID of the connected ECN terminal, used only for terminal-derived task source and response routing.
authrequiredBearerTokenAuth, MTLSAuth, or NoAuth.
tlsverified TLSTLSConfig; must be disabled with the reviewed-container-network attestation.
plaintext_container_networkNoneReviewedContainerNetwork operator attestation, mutually required with NoAuth.
wire_formatJSONJSON or protobuf payloads; MQTT v5 remains fixed.

Path-backed CA, client-certificate, and key material is snapshotted on every connection attempt so atomic replacement can take effect. Each path must open as a non-empty regular file (a symlink to a regular file is accepted), each material value is limited to 1 MiB, each encoded path to 16 KiB, and an encrypted-key password to 64 KiB. Secret values and credential-bearing paths are omitted from public errors.

FieldDefaultMeaning
connection_timeout10 secondsInitial credential-resolution-through-CONNACK deadline and post-ready per-attempt bound; startup owns no subscription.
operation_timeout30 secondsGeneral operation bound, including restored SUBSCRIBE/SUBACK clipped by a configured recovery elapsed deadline.
task_timeout10 secondsDefault task response bound.
shutdown_timeout5 secondsWhole-client cleanup bound.
reconnect_policyReconnectPolicy()Full-jitter backoff, stable reset, and optional recovery attempt/elapsed budgets.
FieldDefaultMeaning
watcher_buffer_size256Maximum bounded event buffer per watcher.
maximum_payload_size1 MiBMaximum accepted or emitted payload.
maximum_outstanding_operations128Bound on correlated task work.
allow_insecureFalseExplicit opt-in accepted only for loopback mock use.

JSON payloads additionally enforce a fixed 64-level container nesting bound in both directions. The bound is not configurable and matches the protobuf group-depth bound on every supported Python version: deeper values are rejected as unsupported values on encode and as malformed payloads on decode.

Profiles use ntp_host and ntp_port; automation may override them with ECN_NTP_HOST and ECN_NTP_PORT. The clock API accepts no per-call host. Use an alternate endpoint only when Picogrid provided it for the configured ECN.

Profiles may also contain a reconnect_policy object with the same six fields as ReconnectPolicy. Supply only the fields you intend to override when running configure; automation can override individual fields after profile loading:

configure optionEnvironment variablePolicy field
--reconnect-initial-delay-secondsECN_RECONNECT_INITIAL_DELAY_SECONDSinitial_delay_seconds
--reconnect-multiplierECN_RECONNECT_MULTIPLIERmultiplier
--reconnect-maximum-delay-secondsECN_RECONNECT_MAXIMUM_DELAY_SECONDSmaximum_delay_seconds
--reconnect-stable-reset-secondsECN_RECONNECT_STABLE_RESET_SECONDSstable_reset_seconds
--reconnect-maximum-attemptsECN_RECONNECT_MAXIMUM_ATTEMPTSmaximum_attempts
--reconnect-maximum-elapsed-secondsECN_RECONNECT_MAXIMUM_ELAPSED_SECONDSmaximum_elapsed_seconds

Omitted values retain the ReconnectPolicy defaults. Environment values override the corresponding stored profile values; blank environment values are ignored. All values receive the same validation as direct configuration. The delay, reset, and elapsed values are seconds; the attempt budget is a positive integer. The two maximum budgets remain unlimited when omitted.

The legion provider follows the behavior pinned from picogrid/legion-system-auth@9f618b7ce1648789d816a49b8fd0ec0ab21ea24a. On every connect and reconnect, it rereads the current access-token record and the non-secret integration configuration. The source integrationId becomes the MQTT username and the current access token becomes the MQTT password. No other field is used for broker authentication.

The provider rejects missing, malformed, expired, symlinked, non-regular files, files with unsafe permissions, and unexpectedly large files. It does not select, expose, or use refresh tokens or client secrets, call the Legion cloud API, refresh a token, install software, run sudo, or modify a service. If local authentication is not configured, follow the official setup instructions and run legion-auth setup yourself.

For a Picogrid-provided non-default storage reference, set ECN_LEGION_AUTH_STORAGE to that same value and run legion-auth setup --storage-path "$ECN_LEGION_AUTH_STORAGE". The SDK never prints the expanded path in diagnostics. LEGION_AUTH_STORAGE_PATH is retained as a compatibility alias for an existing local legion-system-auth installation; ECN_LEGION_AUTH_STORAGE takes precedence when both are set. The alias also works without a named profile.

Certificate and private-key material may come from a path or in-memory SecretStr, never both. Static bearer authentication requires a provided MQTT username for non-loopback use and accepts exactly one of a SecretStr, a cooperative async TokenProvider, or a cooperative async paired CredentialsProvider. Provider callables are validated before invocation; callers that need blocking work must own and bound it explicitly. The token is the MQTT CONNECT password. mTLS always requires TLS.

NoAuth and plaintext_container_network form the only credential-free configuration. TLS must be disabled explicitly; bearer, provider, mTLS certificate, and key material are rejected. On each connect or reconnect, every resolved address must be private. A mixed private/public answer raises TransportBoundaryError, and the SDK dials the validated address literal rather than resolving the hostname again.

import os
from pydantic import SecretStr
from picogrid_ecn_client import BearerTokenAuth, ECNConfig
config = ECNConfig(
host=os.environ["ECN_HOST"],
mqtt_port=int(os.environ["ECN_MQTT_PORT"]),
integration_name=os.environ["ECN_INTEGRATION_NAME"],
auth=BearerTokenAuth(
username=os.environ["ECN_MQTT_USERNAME"],
token=SecretStr(os.environ["ECN_BEARER_TOKEN"]),
),
)

See authentication, security and credentials, and the runnable preflight example.

Version 0.2.0 · branch main