BizFirst Observe
Allowed Telemetry
Not all telemetry is forbidden from crossing the TEE boundary — only telemetry that could reveal protected computation data. Aggregated metrics, sanitized structured logs, and trace identifiers (not span content) are all permissible with proper design. This page specifies exactly what is allowed and how to emit it correctly.
Allowed Telemetry Categories
| Category | Allowed | Conditions | Examples |
|---|---|---|---|
| Aggregated metrics | Yes | No individual record data in labels; no payload values in counters | workflow execution count, node duration histogram, error rate |
| Sanitized structured logs | Yes | No form field values, no computation results, no user data in message or attributes | workflow started/completed/failed, node started/completed, step count |
| Trace identifiers | Yes | TraceId and SpanId only — not span names, span attributes, or span events | TraceId for correlation; SpanId for parent linkage |
| Attestation reports | Yes | Cryptographic proof only — contains measurement (code hash), not runtime data | PCR values, attestation certificate |
| Health check status | Yes | Binary healthy/unhealthy only; no detail about computation state | "processengine: healthy", "db: healthy" |
| Error codes (not messages) | Yes | Numeric codes or short enum-style codes without interpolated values | E_OVERFLOW, E_TIMEOUT, E_AUTH_FAILED |
Allowed Metrics: Correct Emission Pattern
// TEE-safe metric emission in BizFirstGO process engine
// CORRECT: Aggregated counts and durations — no payload data
// Workflow execution counter — labels: tenant (hashed), outcome, node_type
// NOT: tenant=acme-corp (company name is sensitive in TEE context)
// YES: tenant=t_8f3a2b1c (deterministic hash of tenant ID)
_workflowExecutionsCounter.Add(1,
new KeyValuePair<string, object?>("tenant_hash", HashTenantId(tenantId)),
new KeyValuePair<string, object?>("outcome", "completed"),
new KeyValuePair<string, object?>("workflow_type", workflowType)); // enum, not user data
// Duration histogram — no payload reference in any attribute
_nodeDurationHistogram.Record(elapsedMs,
new KeyValuePair<string, object?>("node_type", "calculation"),
new KeyValuePair<string, object?>("outcome", "success"));
// NOT: new KeyValuePair("input_range", "0-1000000") — reveals computation class
// HIL pending count — tenant-scoped gauge
_hilPendingGauge.Set(pendingCount,
new KeyValuePair<string, object?>("tenant_hash", HashTenantId(tenantId)));
// FORBIDDEN metric label patterns in TEE:
// "amount_bucket" = "100k-500k" — reveals financial data class
// "applicant_id" = "usr-12345" — individual identifier
// "form_field" = "income" — reveals what was computed
// "result" = "approved" — reveals computation outcome (if sensitive)
Allowed Logs: Correct Sanitization Pattern
// TEE-safe log emission
// CORRECT: Operational context only — no payload data
// Workflow lifecycle events
_logger.LogInformation("Workflow started. executionId={ExecutionId} workflowType={WorkflowType} tenantHash={TenantHash}",
executionId, // GUID — no payload encoded
workflowType, // enum string — not user-supplied data
HashTenantId(tenantId)); // hashed — not the actual tenant name
_logger.LogInformation("Node completed. executionId={ExecutionId} nodeType={NodeType} durationMs={DurationMs}",
executionId,
nodeType,
elapsedMs); // duration — operational, not payload
_logger.LogError("Node failed. executionId={ExecutionId} nodeType={NodeType} errorCode={ErrorCode}",
executionId,
nodeType,
"E_CALCULATION_OVERFLOW"); // error code — not the values that caused it
// FORBIDDEN log patterns in TEE:
// "Processing income={Income} for applicant={ApplicantName}" — payload data
// "Calculation result: {Result} for form field {FieldName}" — computation output
// "Exception: System.OverflowException: value 1500000 > max" // value revealed in exception
// "Retrying after {StatusCode} from {ExternalServiceUrl}" // if URL reveals data class
Allowed Trace Context: Identifiers Only
// TEE trace context: pass TraceId across boundary, keep span content inside TEE
// ALLOWED: TraceId and SpanId in log correlation fields
_logger.LogInformation("Workflow step completed. executionId={ExecutionId} traceId={TraceId} spanId={SpanId}",
executionId,
Activity.Current?.TraceId.ToString(),
Activity.Current?.SpanId.ToString());
// ALLOWED: TraceId in sanitized log for correlation to in-TEE span store
// The TraceId allows: "when did this workflow run?" (correlated via in-TEE span store)
// The TraceId does NOT reveal: what the workflow computed
// FORBIDDEN: Full span data crossing the TEE boundary
// span.SetTag("income", calculationInput.Income); // payload in span attribute
// span.SetTag("result", calculationOutput.Decision); // computation result
// span.SetTag("applicant.name", applicant.DisplayName); // PII
// TEE trace strategy:
// 1. Emit TraceId + SpanId in sanitized logs (allowed to cross boundary)
// 2. Store full span details in in-TEE Tempo (stays inside TEE)
// 3. External Tempo only receives: trace context propagation (W3C TraceContext header)
// — not the span content itself
Telemetry Contract Definition Template
# TEE Observability Contract — define before first deployment
# Changes to this contract require code modification + re-attestation
ALLOWED_METRICS:
- name: bizfirst_workflow_executions_total
labels: [tenant_hash, workflow_type, outcome]
forbidden_labels: [tenant_name, applicant_id, form_type, amount_range]
- name: bizfirst_node_execution_duration_seconds
labels: [tenant_hash, node_type, outcome]
forbidden_labels: [input_class, result_category]
- name: bizfirst_hil_pending_count
labels: [tenant_hash]
forbidden_labels: [approval_type, approver_id]
ALLOWED_LOG_FIELDS:
- executionId # GUID — no payload encoded
- workflowType # enum — not user-supplied
- nodeType # enum — not user-supplied
- tenantHash # SHA256(tenantId) — not the actual tenant identifier
- durationMs # operational timing — not payload
- errorCode # enum error code — not interpolated values
- traceId # GUID — correlation only
- spanId # GUID — correlation only
- stepCount # integer count — not payload values
FORBIDDEN_LOG_FIELDS:
- Any form field name or value
- Any computation input or output value
- Any user identifier (name, email, ID)
- Exception messages containing data values
- External service responses containing data
The Telemetry Contract Is a Security Boundary
Every field that crosses the TEE boundary is a potential exfiltration vector. Define the allowed telemetry contract as a formal list before deployment. When reviewing code changes to BizFirstGO running inside a TEE, check every logging statement and metric emission point against this contract — not just by convention, but as a security review gate.