Browse documentation

Docs/Reference

Fleet Analytics V1

The exact bucket, metric, privacy, coverage and archive rules that every V1 producer, importer and aggregator must enforce.
Packagerustyauth.analytics.v1
Bucket widthFive minutes
CompatibilityUnknown versions rejected
Normative for M9 and later

The checked-in Protobuf, Parquet schema and golden fixtures are executable parts of this contract. Connector framing, GreptimeDB tables and SQL remain internal implementation details.

Compatibility identity

LayerV1 identityPurpose
Protobufrustyauth.analytics.v1Message and closed-enum compatibility
Batchtransport_schema_version = 1Delivery framing and resource limits
MetricsMETRIC_SCHEMA_VERSION_V1Names, units, dimensions and arithmetic
Parquetrustyauth-metric-bucket-v1Portable archive and deterministic repair
Manifestmanifest_schema_version = 1Integrity, identity and import idempotency

A receiver rejects an unknown version or unknown V1 field. It never guesses a schema from release metadata, silently maps an unknown enum to “other,” or reinterprets incompatible input as V1.

Window and retry contract

  • Every bucket is exactly five minutes, UTC-aligned and left-closed/right-open.
  • Event time selects the bucket; receipt time never rewrites it.
  • V1 sends closed buckets only. The default close grace is two minutes.
  • The first revision is 1. A correction increments the revision and resends the complete snapshot.
  • A retry reuses the exact canonical key and revision; it never sends a counter delta.
  • A batch carries at most 288 buckets and encodes to at most 256 KiB.
(realm_id, assignment_epoch, bucket_start_unix_milliseconds,
 bucket_width_seconds, metric_schema_version)

That tuple identifies the canonical bucket. revision selects the accepted value for it. Event sequence bounds are both zero when no durable event contributed; otherwise they form an ordered positive range.

Metric families and aggregation

An absent family means unsupported or unavailable. A present family of zeros means supported with no observed activity. Registry-backed coverage preserves that distinction for every customer-facing result.

FamilyV1 factsAggregation
AuthenticationAttempts, successes, failures, denials, active account observationsSum counts; derive success rate from summed counts
LatencyAuthentication, API, SableDB and delivery count/sum/histogramMerge compatible cumulative histograms before percentiles
RegistrationOptions, ceremonies, responses, completions and expiriesSum every funnel stage independently
Sessions and tokensSessions created/revoked; user/service tokens issuedSum counts
Service accountsCalls, outcomes, denials and credential rotationsSum counts
WebhooksDeliveries, outcomes, latency and latest backlogSum events; latest backlog per realm
PlatformAPI and SableDB requests, errors and latencySum counts; merge histograms
Realm healthServing state, backup age, key age and connector lagLatest realm observation plus coverage
Active account observations are not unique people

active_account_observations counts distinct realm accounts within one bucket. Summing it produces account-window observations: the same account can contribute in multiple windows and one person may have accounts in multiple realms.

Required invariants

authentication attempts = successes + failures + denials
service-account calls    = successes + failures + denials
webhook deliveries       = successes + failures

options_started >= ceremonies_opened
                >= responses_returned
                >= registrations_completed

Authentication flow and failure-class breakdowns must exactly reproduce their headline totals. Expired registrations are outside the funnel ordering because a challenge may expire in a later window. Counters are capped at 1,000,000,000 per realm bucket, sums use checked arithmetic, and impossible relationships or duplicate enum dimensions fail closed.

Fixed histogram profiles

Each histogram contains cumulative counts for every bound and a final +Inf count equal to count. Counts must be monotonic. Percentiles use the upper bound of the first merged cumulative bucket meeting the nearest-rank threshold.

Interactive milliseconds V1

5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000, +Inf

Used for authentication, API and SableDB latency.

Delivery milliseconds V1

10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000, 30000, +Inf

Used for webhook delivery latency. A value falling only in +Inf has no finite upper bound.

Bounded dimensions and privacy

V1 has no label map and accepts no caller-named dimension. A realm may send only closed Protobuf enums for authentication flow, failure class, metric family, histogram profile, serving state, acknowledgement and rejection reason, plus its stable realm identity and assignment epoch.

realm_id is the same stable 1–64 character ASCII identifier accepted by realm configuration and Fleet pairing; it is not required to be a UUID. Batch and manifest IDs remain canonical UUID idempotency keys.

Fleet resolves organization, project and environment from the authenticated connection. Those hierarchy values are never trusted from a realm payload.

The following are prohibited in metrics, dimensions, manifests and acknowledgements:

  • user, subject, account, credential, challenge, session, token and request IDs;
  • email, phone, name, IP address, user agent and arbitrary path values;
  • RP assertions, public keys, cookies, secrets and secret hints;
  • webhook URLs, error messages and caller-defined labels; and
  • presigned URLs or object-store credentials.

Batch and manifest UUIDs are transport idempotency keys, not queryable dimensions. Event sequences are watermarks.

Coverage arithmetic

expected_realms = reporting_realms + stale_realms
total_realms    = expected_realms + disabled_realms + unsupported_realms
partial         = reporting_realms < expected_realms

Coverage is metric-family-specific. The last complete window is zero when no complete common window exists; otherwise it is a UTC-aligned five-minute instant.

Signed Parquet archive

A V1 archive uses Zstandard Parquet with one row per complete bucket snapshot and revision. Physical Parquet bytes are not golden because writer metadata and page layout may differ; the versioned logical-row schema fixes field IDs, enum numbers and meaning.

After publication, the object is immutable. Its manifest binds the exact schema versions, realm, assignment epoch, credential-free object key, SHA-256 digest, byte length, row count, bucket and sequence ranges, creation time, signing-key ID and raw 64-byte P-256 signature.

rustyauth.analytics.metric-bucket-manifest.v1
NUL
deterministic protobuf manifest with signature unset

The importer verifies the approved bucket binding, signature, digest, size, row count, time and sequence ranges before reading a row, then records manifest identity and digest for retry idempotency. V1 has no raw-event or subject-level archive row.

Deterministic scope results

  • Derive every numerical scope directly from canonical realm buckets for the requested assignment epochs.
  • Calculate rates from summed numerators and denominators; never average child percentages.
  • Merge compatible cumulative histograms before calculating percentiles.
  • Select the latest accepted gauge per realm before scope summation or classification.
  • On correction, recompute the affected time range from the highest accepted revisions.

Change policy and executable references

Adding an enum is additive to Protobuf but requires a new metric schema before a realm emits it. A changed unit, histogram boundary, aggregation rule, invariant, Parquet meaning or privacy rule always requires a new metric schema. Field numbers and Parquet field IDs are never reused.