Files
zeekayandHanzo Dev 212410de59 The warehouse is reached as an IAM identity, never a password
A telemetry store now presents an IAM access token minted for the
datastore audience at every handshake, and has no other credential to
present. The token is the embedding process's identity, set by the host
rather than read from configuration: the standalone server mints its own
from IAM_CLIENT_ID and IAM_CLIENT_SECRET, and cloud hands the embed the
identity its o11y app already holds.

A DSN now says where the warehouse is and nothing else. One that names a
user or password is refused, and a store with no identity is not built.
Pooled connections live five minutes, so each replacement presents a
current token and a revoked identity keeps nothing for long.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-24 14:35:36 -07:00

86 lines
2.9 KiB
Go

package telemetrystore
import (
"context"
"time"
"github.com/hanzoai/o11y/pkg/factory"
)
type Config struct {
// Provider is the provider to use
Provider string `mapstructure:"provider"`
// Connection is the connection configuration
Connection ConnectionConfig `mapstructure:",squash"`
// Datastore is the datastore (Datastore-protocol) configuration
Datastore DatastoreConfig `mapstructure:"datastore"`
}
type ConnectionConfig struct {
// MaxOpenConns is the maximum number of open connections to the database.
MaxOpenConns int `mapstructure:"max_open_conns"`
// MaxIdleConns is the maximum number of connections in the idle connection pool.
MaxIdleConns int `mapstructure:"max_idle_conns"`
// DialTimeout is the timeout for dialing a new connection.
DialTimeout time.Duration `mapstructure:"dial_timeout"`
}
type DatastoreConfig struct {
// DSN is the database source name: where the warehouse is, never who is
// asking. A DSN that carries a user or password is refused.
DSN string `mapstructure:"dsn"`
// Token answers the IAM access token every warehouse connection presents,
// minted for the "datastore" audience. The warehouse trusts Hanzo IAM and no
// stored secret, so this is the only credential a connection carries, and it
// is asked at every handshake so a renewing source keeps each new connection
// current. It is the embedding process's identity and is never read from
// configuration: the host sets it (cmd/community for the standalone server,
// hanzoai/cloud for the embed) before the store is built.
Token func(context.Context) (string, error) `mapstructure:"-" json:"-" yaml:"-"`
// Cluster is the cluster name to use for datastore.
Cluster string `mapstructure:"cluster"`
// QuerySettings is the query settings for datastore.
QuerySettings QuerySettings `mapstructure:"settings"`
}
type QuerySettings struct {
MaxExecutionTime int `mapstructure:"max_execution_time"`
MaxExecutionTimeLeaf int `mapstructure:"max_execution_time_leaf"`
TimeoutBeforeCheckingExecutionSpeed int `mapstructure:"timeout_before_checking_execution_speed"`
MaxBytesToRead int `mapstructure:"max_bytes_to_read"`
MaxResultRows int `mapstructure:"max_result_rows"`
IgnoreDataSkippingIndices string `mapstructure:"ignore_data_skipping_indices"`
SecondaryIndicesEnableBulkFiltering bool `mapstructure:"secondary_indices_enable_bulk_filtering"`
}
func NewConfigFactory() factory.ConfigFactory {
return factory.NewConfigFactory(factory.MustNewName("telemetrystore"), newConfig)
}
func newConfig() factory.Config {
return Config{
Provider: "datastore",
Connection: ConnectionConfig{
MaxOpenConns: 100,
MaxIdleConns: 50,
DialTimeout: 5 * time.Second,
},
Datastore: DatastoreConfig{
DSN: "tcp://localhost:9000",
Cluster: "cluster",
},
}
}
func (c Config) Validate() error {
return nil
}