| D-M6-14-1 |
2026-10-25 |
getStatsTimeline authorizes stats.read on the instance or the space first (403, 404 for an unreadable space), then checks the range: from before to, both on full minutes, to - from at most stats.timeline_max_range, from not before now - retention.stats_minutes, each violation 400 validation_failed with one field error (invalid_range, not_full_minute, range_too_long, outside_retention). The channel set is the one of M6-05 (Scope(message.read) kept to channels with a space, with a space to that space); cost.read.aggregate on the same target decides in filter mode whether cost is among the read metrics. Rows: stats_minutes with bucket_start in [from, to), the requested metrics (all of 25 3.2 without metric), the channel in the set, rows without a channel only for an owner on the instance, filtered again in memory. Runs: the threads of the channel set through chat.StatsSource, then runs.TimelineSource with stats.timeline_max_runs plus one; a run counts when queued_at < to and it has not finished before from; ordered by queued_at, then ID; runs_truncated when the extra run came back. The result is not cached. |
Brief, design note 1; 25 6.5 and 11. The runs table has no channel_id (D-M2-05-9), so the thread set of M6-05 bounds the runs. |
| D-M6-14-2 |
2026-10-25 |
getStatsSlo needs stats.read on the instance; per entry of slibounds.gen.go, ordered by SLO name, it sums count and good of the metric over all rows with bucket_start in [now - period, now) (the read port SLITotals of M7-09, summed over the dimensions), then domain.EvaluateSLO: insufficient_data below stats.slo_min_events events, else red at a remaining budget of 0 or less, amber below stats.slo_warn_budget_ratio, else green; ratio and budget_remaining only with at least one event; threshold_ms only for a latency SLO. The report is cached for stats.cache_ttl in the cache of M6-05 under one key for every owner, because it shows only values of the whole instance. |
Brief, design note 2; 25 6.4; VZ-T09. |
| D-M6-14-3 |
2026-10-25 |
getStatsBackends shows the agents with a run in a visible channel whose interval intersects the range (runs.TimelineSource.TimelineAgents) and the effective operators of the visible channels (chat.ChannelPlaces). Per agent: the configured and reported mode, the supported modes and the stored rate_limit through agents.BackendSource; invocations_denied and cost summed over the visible channels; billing_mode_switches, which has no channel, summed for the agents of the result for every caller who sees them. Costs come from the own measurement, which is no billing record and does not follow reconciliation, so every amount has is_estimate true; amounts of mode personal appear only with billing.show_personal_estimates, as in getCostStats. The range needs from before to and not before now - retention.stats_minutes; a row counts when its minute starts in the range. |
Brief, design note 3; 25 6.2; 10 12.2. |
| D-M6-14-4 |
2026-10-25 |
The backend view never sends adapter_kind, runtime_version, billing_evidence, the runtime or adapter name of reported_details, a credential holder or any other credential data: agents.BackendState carries none of them and the schema StatsBackendAgent has no member for them; the integration test checks the encoded members against the schema. |
Ruling T8, I5. |
| D-M6-14-5 |
2026-10-25 |
The heartbeat decodes rate_limit in the agents domain: state from ok, near_limit, limited, unknown, resets_at optional and an RFC 3339 time, any other member refused; the stored JSON is exactly {state, resets_at?} with resets_at in UTC milliseconds. resets_at has no window bound: the server only shows it, and a provider window lasts from a minute to a billing month. A heartbeat without the member clears the stored value at its next write, because every heartbeat is the full reported state; a change of rate_limit alone is never audited (catalogue row agent.heartbeat). |
Brief, design note 4; 09 4.8. |
| D-M6-14-6 |
2026-10-25 |
Python: build_heartbeat(rate_limit=...) takes the generated AgentRateLimitState or a mapping with state and a timezone-aware resets_at (converted to UTC), and RuntimeStatus.rate_limit passes it through the adapter. TypeScript: buildHeartbeat(state, { rateLimit }) takes the generated type with an RFC 3339 resets_at that names a time zone. Both refuse any other member or value with the field name; both FakeServers check rate_limit like the server. |
Brief, design note 5. |
| D-M6-14-7 |
2026-10-25 |
Names differ from the brief and follow the code: runs has no channel_id, so runs.TimelineSource takes the thread set of the visible channels and stats maps each run to its channel; the port of the three use cases is stats.Views (statsapp.Views, handlers statshttp.Views); the integration tests are subtests of TestStatsViews in internal/wire (Timeline_SpaceManager, Timeline_Owner, Timeline_Range, Slo_OwnerOnly, Backends, NoPeopleNoContent) over one started process, and the unit tests without cost.read.aggregate are TestTimeline_WithoutCostRead and TestBackends_WithoutCostRead in internal/stats/app. The live frame keeps rate_limit absent (M6-15 builds it from the presence tracker, not from the stored row). |
Brief names predate the code (D-W-100, D-W-120). |