Publication Boundary
This is the public status boundary to check before treating design notes or plan rows as implemented behavior.
Current public document
Explicit and implicit implementation limits by component.
This is the public status boundary to check before treating design notes or plan rows as implemented behavior.
Unsupported, partial, and gated behavior is intentionally visible rather than softened into product claims.
This file is the current implementation limitations registry. It describes
known boundaries that are enforced by code, required by configuration, or implied
by unfinished roadmap work. Target architecture remains in docs/design.md;
operational backlog status remains in docs/PLAN.md, and completed-slice
history remains in docs/worklog/.
/tmp/lightmetrics-demo by default.0600) independent of ambient umask.
Restart preserves existing secrets without widening permissions.lm-agent --daemon runs repeated heartbeat and configured log_inputs
collection through the same durable queue and upload path as --once.
Production service units, graceful signal handling, and dynamic config reload
are not implemented yet.lmagent_up, aggregate
lightmetrics_host_cpu_seconds_total counters, capped per-core
node_cpu_seconds_total counters for CPU IDs 0 through 7,
node_memory_MemTotal_bytes, node_memory_MemAvailable_bytes,
node_load1, node_load5, node_load15,
lmagent_queue_filesystem_size_bytes,
lmagent_queue_filesystem_avail_bytes,
node_network_receive_bytes_total,
node_network_transmit_bytes_total,
lmagent_process_cpu_seconds_total, and
lmagent_process_resident_memory_bytes. It also emits capped Linux
process-enumeration metrics
lightmetrics_host_process_cpu_seconds_total,
lightmetrics_host_process_resident_memory_bytes, and
lightmetrics_host_processes_omitted for up to eight /proc processes.
Enumerated processes are sorted by resident memory bytes, then CPU ticks, then
PID; metric identity labels are pid, start_time, and comm; command-line
arguments are not read. Non-Linux host APIs and persisted CPU-rate delta
calculation remain planned./proc boundaries cannot
be parsed, the corresponding best-effort counters are omitted for that scrape.ingest.max_series_per_batch >= 107 and
ingest.max_labels_per_series >= 4, with
ingest.max_label_key_bytes >= 14 and
ingest.max_label_value_bytes >= 64 for built-in metric labels and log
attributes; lower values are rejected by collector config validation. The
sample collector config defaults of 2048 series, 32 labels, 128 key bytes, and
512 value bytes satisfy this floor.. or - suffix may not be
found before unread complete lines become unavailable. Trailing partial lines
left in a rotated file are not queued.--once run or daemon
scrape can queue multiple ordered batches when more complete lines are
available than one batch can carry.max_log_message_bytes, exceeds the batch budget after
encoding overhead, or cannot be read within the bounded line window.encoding=utf8_lossy.max_log_message_bytes must be configured no higher than the collector’s
ingest.max_log_message_bytes. The agent cannot discover the collector limit
dynamically.max_logs_per_batch must be configured no higher than the collector’s
ingest.max_logs_per_batch. One configured log slot is used by the heartbeat
log record, so file tailing collects at most max_logs_per_batch - 1 records
per queued batch. If agent-side log limits diverge upward from collector limits,
the collector can reject queued batches after source offsets have advanced.max_alerts_per_batch defaults to one local alert slot for queue-pressure
drop reporting and must be configured no higher than the collector’s
ingest.max_alerts_per_batch. Set it to 0 only when the collector cannot
accept alert records; queue-pressure log drops can then occur without an
uploaded local alert.agent.queue_dropped alert
when max_alerts_per_batch and queue space allow it. If even the metrics-only
batch cannot fit, collection fails without advancing log offsets.Content-Encoding is not supported for batch uploads. Compression is
reserved for frame flags.local_spool and s3_manifest are the implemented ingest acceptance modes.
local_spool acknowledges after durable local spool acceptance and is a
single-collector durability mode, not active-active acceptance.local_spool has a configured object store, accepted batches are landed
asynchronously on ingest.object_landing_interval_ms. Object-store landing
failures are logged and retried by the next background pass, but they do not
reject already accepted local-spool ingest and queries continue to read the
accepted spool before landing.s3_manifest acknowledges only after object-store accepted-manifest
conditional create succeeds. Object-store outages in this mode should become
503 backpressure rather than local acceptance.(agent_id, boot_id, seq_start, seq_end). Same identity with different bytes
is an identity conflict and is not acknowledged as accepted.gcs is
parsed by config but rejected at runtime.accepted-by-time, accepted-by-blob, and raw-blobs-by-time are repairable
side effects.s3_manifest mode and fixed-interval in-process
background reconciliation for configured object stores run accepted-manifest
repair passes for listing-capable backends. The private query listener exposes
the latest reconciliation attempt at
GET /api/v1/object-store/reconciliation. Configurable schedules,
cross-process leader election, S3 Inventory fallback, full cold-scan
scheduling, and rollup enqueueing remain planned. The query path does not
maintain a separate persistent local query cache; derived object indexes are
the rebuildable query-planning side effects, and local .object-landed
markers remain the landed-spool tail boundary.query_range, logs, and alerts requests add an
explicit warning when the requested range extends outside the loaded local
sample, log, or alert horizon, or when no local horizon can be established.object_store_unavailable
query error instead of silently falling back to local data.query_range, logs, and alerts requests, object-store
loading can use accepted-by-time derived indexes to bound accepted-manifest
discovery before reading authoritative accepted manifests and raw blobs. The
index is keyed by acceptance time, not per-sample/log/alert event time; requests
without a closed time range, empty index scans, index read failures, and very
broad index ranges fall back to accepted-manifest listing. Indexed responses
include explicit partial warnings because individual derived index entries can
be missing until reconciliation repairs them.rate() over range
selectors, sum(... ) by (...), histogram bucket virtual series, and
histogram_quantile() in the supported shape.match[] filters
for supported series selectors, including metric-name selectors and label-only
selectors with exact, negative, regex, and negative-regex matchers. Malformed
or unsupported match[] values return Prometheus-style bad_data.query?time=... evaluates supported direct selectors and rate-derived
functions at the requested finite timestamp with the fixed five minute
lookback for direct selectors. Without time, instant vector queries retain
the existing latest-sample behavior.bad_data responses. Binary
operators, joins, subqueries, offset, logical/set operators, arbitrary nested
functions, recording-rule semantics, and broad Prometheus staleness behavior
are not implemented.query_range evaluates samples at start + n * step timestamps with a fixed
five minute lookback. Configured object-store-backed long range queries may
use immutable gauge/counter rollup chunks and compatible histogram
virtual-series rollup chunks when a rollup window fits the query step and
lookback. Exact object-store coverage metadata is not implemented.GET /api/v1/logs?contains=... decodes the query parameter using standard
form query rules, including + as space and percent-decoded UTF-8, then
applies a case-sensitive substring match to the log message field.GET /api/v1/logs/tail is a private SSE endpoint that emits bounded
log_tail_snapshot, log_tail_update, and log_tail_gap events loaded from
the same accepted-log visibility source as GET /api/v1/logs. It supports the
existing log time/agent/boot/severity/target filters, a bounded limit, and
an opaque after cursor for reconnect or lag repair when the request is scoped
to the matching agent_id and boot_id. It is not a durable event journal or
unbounded log stream.contains filtering on GET /api/v1/logs/tail are not
implemented.GET /api/v1/events is a private SSE stream of accepted-batch notices, not a
correctness source. Clients must repair missed ranges by querying persisted
data.query_range over the affected
timestamp interval. Broader multi-series dashboard backfill is not implemented
yet, and the embedded console does not consume GET /api/v1/logs/tail yet.query_range requests,
and falls back to raw accepted data when a selected rollup read returns no
chunks or fails validation. Instant queries, labels, series, logs, and alerts
do not use rollups._bucket, _sum, and _count range results expose
synthetic cumulative window-boundary points derived from merged window deltas
so rate() and histogram_quantile() can compute bounded approximations.GET /api/v1/dashboards is a private
query-token API that exposes the canonical dashboard definition list. Duplicate
custom dashboard IDs and implicit built-in overrides are rejected at config
check/startup. The console loads dashboard tabs/settings from that API after
query-token connection, and configured Prometheus dashboard panels issue
bounded /api/v1/query_range requests with loading, empty, partial-warning,
stale, and error states. Dashboard panel rendering and querying are capped per
dashboard in the browser to bound private query load. The deeper Fleet, Live
metrics, Logs, Alerts, Ingest/storage, and Query utility views are not fully
definition-backed. The Object horizon surface additionally fetches
GET /api/v1/object-store/reconciliation and maps the returned
object-store reconciliation state into disabled, partial, or failed UI, but
exact object-store horizon metadata remains unavailable.localStorage, and Disconnect clears both browser storage scopes. There is no
server-side session management for the private console.docs/docker.md is an operator-owned container recipe, not a supported
packaged artifact.log_inputs.0.0.0.0 inside the container. Restrict the host-side published port
or private network exposure.AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY, and optional AWS_SESSION_TOKEN; config points at the
endpoint, bucket, prefix, and region.site/ is a static Astro scaffold for the public website. It uses npm,
builds static output to site/dist, and does not use a Cloudflare adapter,
SSR, runtime API calls, bearer tokens, or private agent procedure content.README.md, docs/README.md, docs/quickstart.md, docs/install.md,
docs/docker.md, docs/limitations.md, docs/design.md,
docs/active-active-s3-ingest.md, docs/design-artifacts.md,
docs/claude-design-public-site-task.md, docs/PLAN.md, and
docs/gantt-data.json. It writes ignored build metadata and generated
Markdown route inputs under site/src/generated/; that generated data is not
an authoritative replacement for the source files.AGENTS.md, REVIEW.md, docs/worklog/,
and the local docs/gantt-data.js wrapper are excluded from public docs
routes.docs/gantt-data.json payload through the site prebuild metadata step,
renders filters, task details, and a static Gantt timeline, and excludes the
local file:// docs/gantt-data.js wrapper from the public site boundary.
Cloudflare Pages preview configuration is codified through the site/
package’s build settings, wrangler.toml, _headers, _redirects, and deploy
contract check. Actual Cloudflare project/account operations are
operator-dependent, and DNS/custom-domain launch remains gated under WEB-07.rate(), grouped sum(rate(...)), and histogram_quantile() paths against
the local demo. The rate() and histogram dashboard panels use smoke-only
metric data accepted through the real ingest/query path; broader PromQL parity
remains out of scope.When a change adds a new runtime boundary, unsupported behavior, partial response
mode, durability tradeoff, or planned-but-not-implemented feature, update this
file in the same slice. If the limitation is tied to a tracked backlog item,
also update docs/PLAN.md. If the limitation is discovered or changed by a
completed slice, record the completed-slice evidence in the matching
docs/worklog/<TASK-ID>.jsonl record.