/** * Runtime identity stamped onto telemetry: the {@link IdentityEnvelope} and the config fingerprint. * * Because a runtime instance is bound to a single strategy/wallet, `strategyAddress` lives on the * envelope rather than being repeated per signal. * * The hash is computed over the **unresolved** config (raw, pre-`${VAR}`) with canonically sorted * keys: this keeps it stable across secret rotation and deterministic for a byte-identical recipe, * and means it never carries resolved secrets. */ /** * Identity stamped onto every telemetry record/span by the identity stamping layer. * * Producers never pass these fields individually — the layer holds them for its lifetime and applies * them to everything it forwards. Because a runtime instance is bound to a single strategy/wallet, * `strategyAddress` lives here rather than being repeated on each record. */ export interface IdentityEnvelope { /** Logical service name (e.g. the ingestion service identifier). */ readonly service: string; /** Recipe / strategy configuration name (the config's top-level `name`). */ readonly recipe: string; /** Declared config version (the config's optional top-level `version`), when set. */ readonly recipeVersion?: string | number; /** * Content fingerprint of the **unresolved** config (raw, pre env-var substitution), canonically * serialized (sorted keys) and hashed once at boot. Unresolved on purpose: hashing post-`${VAR}` * would (a) put secrets in the hash input and (b) change the key whenever a secret rotates, even * for a byte-identical recipe — the opposite of a "which recipe produced this" join key. Hashing * the raw config makes the key stable across secret rotation and deterministic. Computed upstream * at boot, NOT in any mapper, so a redaction pass can never perturb it. The cross-session join key: * every record carries it via the envelope, while the unresolved config blob lives once on the * runtime-lifecycle record's `config` (hash and blob share the same input). Distinguishes edits * that didn't bump the declared `recipeVersion`. */ readonly configHash?: string; /** Runtime instance name (`runtimeName`). */ readonly runtime: string; /** Strategy identifier = wallet address. */ readonly strategyAddress: string; /** * Deployment / installation group (the config's optional top-level `group`), when set. The fleet * key the install flow stamps: it answers "same strategy failing across many boxes" and "one wallet * of a multi-wallet install" — questions `strategyAddress` + `user.id` alone can't. Per-runtime (a * multi-wallet install can run one group per wallet in one process), so it rides the identity bag, * never the process-global resource (see `trace-identity.ts`). */ readonly group?: string; /** Unique id for this process boot, to disambiguate restarts. */ readonly bootId: string; } /** Logical producer name stamped as `service.name`. Must stay `senpi-trading-runtime`: * it matches the sibling ingestion service's documented convention and the rows already in its * ClickHouse tables, where `ServiceName` is part of the sort key. */ export declare const SERVICE_NAME = "senpi-trading-runtime"; /** SHA-256 hex of the canonicalized unresolved config; `undefined` when no config is available. */ export declare function computeConfigHash(unresolvedConfig: Record | undefined): string | undefined; export interface BuildIdentityParams { /** Recipe / runtime name (the config's top-level `name`). */ readonly name: string; readonly recipeVersion?: string | number; /** Strategy identifier = wallet address. */ readonly strategyAddress: string; /** Deployment / installation group (the config's optional top-level `group`). */ readonly group?: string; /** Per-process boot id. */ readonly bootId: string; /** Unresolved config, used to fingerprint the recipe (`configHash`). */ readonly unresolvedConfig?: Record; } export declare function buildIdentity(params: BuildIdentityParams): IdentityEnvelope; //# sourceMappingURL=identity.d.ts.map