summaryrefslogtreecommitdiffstats
path: root/docs/FOG-OBSERVABILITY.md
diff options
context:
space:
mode:
authorGab <24553253+gabrix73@users.noreply.github.com>2026-08-18 21:43:48 +0200
committerGab <24553253+gabrix73@users.noreply.github.com>2026-08-18 21:43:48 +0200
commit25356debcce4118cdfa86842029278fde1e64518 (patch)
treee2b681576fb7163ee83006a74b62013e63706c29 /docs/FOG-OBSERVABILITY.md
parent6974e5459608feed48c611c76622226d2fc4fe26 (diff)
downloadfog-25356debcce4118cdfa86842029278fde1e64518.tar.gz
fog-25356debcce4118cdfa86842029278fde1e64518.tar.xz
fog-25356debcce4118cdfa86842029278fde1e64518.zip
Publish FOG design documentation and Merkle tree
Diffstat (limited to 'docs/FOG-OBSERVABILITY.md')
-rw-r--r--docs/FOG-OBSERVABILITY.md718
1 files changed, 718 insertions, 0 deletions
diff --git a/docs/FOG-OBSERVABILITY.md b/docs/FOG-OBSERVABILITY.md
new file mode 100644
index 0000000..b72034f
--- /dev/null
+++ b/docs/FOG-OBSERVABILITY.md
@@ -0,0 +1,718 @@
+# FOG Observability
+
+Status: Structural Baseline 0.1
+
+Date: 2026-08-08
+
+## 1. Purpose and Claim Boundary
+
+`FOG-OBSERVABILITY-1` defines privacy-safe local logging, operational metric
+collection, aggregate submission, operator diagnosis, and public health
+publication for FOG.
+
+The objective is to detect failed or unsafe role state without creating a
+second traffic-analysis system. Observability is part of the threat model. A
+log server, tracing system, dashboard, crash collector, or support workflow
+can otherwise preserve exactly the timing and relationship metadata that the
+data plane is intended to minimize.
+
+This baseline fixes:
+
+- a no-event-stream production default;
+- a closed metric and local-summary vocabulary;
+- coarse non-overlapping collection windows;
+- bucketed values and low-activity suppression;
+- delayed role-to-observer submissions;
+- separate local, operator, and public views;
+- public anti-differencing requirements;
+- bounded local retention and raw-submission expiry;
+- crash, support, debug, access, and conformance rules.
+
+It does not activate a numeric observability profile. Window duration, bucket
+boundaries, minimum activity, minimum independent reporters, release delay,
+merge policy, retention, serialization, signature suite, and public grouping
+remain explicit evidence-gated selections. No implementation or deployment
+may silently choose them as protocol defaults.
+
+The standard-library Go module in `../observability/` is an executable
+conformance model for the role-local typed collector and bounded volatile
+ring. Its test values are synthetic. It is not `fog-observer`, an IF-11 wire
+codec, a signature implementation, or a public exporter.
+
+## 2. Governing Requirements
+
+This document refines:
+
+- `TM-OPS-01`, logging and metrics leakage;
+- `TM-NET-01`, timing and volume correlation;
+- `TM-NET-03`, active suppression and n-1 behavior;
+- `TM-ROLE-01` through `TM-ROLE-03`, role compromise and collusion;
+- `TM-AVAIL-01`, bounded work and overload handling;
+- `ARC-001`, separate trust domains;
+- `ARC-007`, one owner for private state and keys;
+- `ARC-008`, bounded inputs, work, queues, and state;
+- `ARC-009`, no privacy-weakening recovery;
+- `IF-11`, role-to-observer aggregate submission;
+- the logging sections of `FOG-WIRE`, `FOG-SPHINX-PROFILES`,
+ `FOG-STORAGE`, and `FOG-COMPOSER`.
+
+When this document is narrower than a generic logging or monitoring practice,
+this document controls for claim-bearing FOG profiles.
+
+## 3. Threat Model
+
+The protected assets are:
+
+- whether one user, peer, mailbox, route, packet, or conversation was active;
+- exact event time, direction, sequence, size, and duration;
+- linkability across roles, hosts, epochs, restarts, or support cases;
+- capabilities, keys, tokens, replay state, and opaque protocol objects;
+- operator, host, deployment, and user metadata not already required in
+ authenticated public consensus.
+
+Relevant adversaries include a compromised role, observer, dashboard,
+operator account, support system, backup, or log collector, as well as an
+external party that later obtains retained operational data. A curious or
+compromised observer is within scope. The design therefore does not assume
+that centralizing raw logs is safe.
+
+No observability design can hide what a node operator sees directly on that
+node or what a network observer sees on links. The goal is narrower: do not
+create a new persistent, cross-role, queryable correlation dataset.
+
+## 4. Invariants
+
+### OBS-INV-01: No data-plane event stream
+
+Production roles do not emit one record for each packet, message, handshake,
+storage request, read, write, retry, connection, or cryptographic operation.
+They update bounded in-memory counters or health state inside one coarse
+window.
+
+### OBS-INV-02: Closed typed vocabulary
+
+Every field, role, metric, state, failure class, value kind, and visibility
+class is allowlisted. Production collection APIs accept no arbitrary label
+map, free-form message, raw error, peer-provided string, path, address, or
+identifier.
+
+### OBS-INV-03: Coarse windows only
+
+A role records one window identifier, not event timestamps. Windows are
+profile-fixed, aligned, and non-overlapping. Operators and public consumers
+cannot request arbitrary time ranges.
+
+### OBS-INV-04: No exact exported traffic values
+
+Raw counters exist only inside the open volatile collector. Sealing converts
+them to profile-defined buckets. Exact counts, sizes, latencies, ratios, queue
+depths, and durations do not enter local summaries, observer submissions, or
+publications.
+
+### OBS-INV-05: Suppress small activity sets
+
+Below the profile's minimum activity, every traffic-sensitive metric carries
+the fixed `suppressed` value. Suppression does not remove fields or change the
+report shape. Non-traffic health state may remain available.
+
+### OBS-INV-06: Delayed fixed-schedule submission
+
+Online roles submit on a profile-fixed schedule independent of whether real
+traffic occurred. Each submission declares the earliest release window.
+Immediate event-triggered submission is forbidden.
+
+### OBS-INV-07: Public output requires multiple reporters
+
+No role-local report can become a public report. `fog-observer` first combines
+the profile-required number of independently authenticated reporters, then
+applies coarsening, delay, suppression, and differencing controls.
+
+### OBS-INV-08: No cumulative or subtractable public series
+
+Public output does not expose cumulative counters, overlapping query windows,
+arbitrary filters, node-level series, or stable dimensions that allow two
+answers to isolate a smaller group.
+
+### OBS-INV-09: Bounded retention
+
+Local summaries use a bounded volatile ring or a profile-authorized protected
+store. Raw signed observer submissions expire after bounded processing.
+Retention is fixed in the active profile and cannot be extended through a
+dashboard query or support request.
+
+### OBS-INV-10: Observability is not required for forwarding
+
+Failure, absence, overload, or compromise of `fog-observer` does not alter
+packet forwarding, consensus validity, storage behavior, cover scheduling, or
+cryptographic validation. Roles queue at most a bounded aggregate submission
+and otherwise discard it.
+
+### OBS-INV-11: Production tracing is unavailable
+
+Claim-bearing builds have no packet, record, request, span, or connection
+tracing mode. `DEBUG` or `TRACE` cannot be enabled by runtime configuration.
+Synthetic conformance builds are a separate artifact rejected by production
+configuration.
+
+### OBS-INV-12: Fixed shape within role and profile
+
+Every local summary and observer report contains the same ordered metric
+positions for its role and profile. Unset values are `unknown` or `zero`.
+Sensitive low-activity values are `suppressed`. Presence or field order does
+not reveal which code path ran.
+
+## 5. Information Planes
+
+FOG uses three observability planes:
+
+1. **Local safety summary**: one role retains bounded coarse windows needed
+ for local diagnosis. It never contains event records.
+2. **Operator aggregate**: an online role sends a delayed fixed-shape
+ aggregate over mutually authenticated IF-11. The observer may use it for a
+ protected operator health view.
+3. **Public aggregate**: the observer combines enough independent reporters
+ and publishes only a delayed, coarsened, non-subtractable view.
+
+```text
+role-local raw counters, volatile within one window
+ |
+ | seal once, bucket, suppress
+ v
+ bounded local summary + delayed IF-11 aggregate
+ |
+ | authenticate, combine, expire raw
+ v
+ operator view public view
+ protected delayed and multi-reporter
+```
+
+The networkless Composer and `fog-sx-send`/`fog-sx-receive` do not submit
+automatic observer reports. They may retain only the local safety summary
+allowed by their deployment profile.
+
+## 6. Data Classes
+
+The following classes are forbidden in every FOG log, metric, report,
+dashboard, crash artifact, and generic support bundle:
+
+- plaintext, drafts, rendered content, contacts, labels, fingerprints, and
+ application fields;
+- packet or record bytes, ciphertext samples, entry capsules, KEMSphinx
+ packets, storage envelopes, and imported attacker input;
+- capabilities, vouchers, SURBs, reply material, replay tags, receipt
+ material, ratchets, storage streams, and secret or private key material;
+- message, session, packet, request, record, box, receipt, connection, trace,
+ span, route, or bundle identifiers;
+- source or destination IP address, peer ID, next-hop ID, full route, replica
+ selection, entry set, or per-source history;
+- exact event timestamps, per-operation duration, direction trace, retry
+ sequence, queue item, read frequency, miss streak, and tombstone timing;
+- raw error strings, parser offsets, expected values, detailed cryptographic
+ stages, stack traces, memory dumps, or exception objects;
+- hostname, username, filesystem path, locale, timezone, device serial,
+ billing data, private operator contact, or infrastructure detail absent from
+ the authenticated public consensus.
+
+Hashes, truncation, encryption under a central log key, or pseudonymization do
+not make a forbidden identifier safe. A stable digest remains a correlation
+handle.
+
+## 7. Production Defaults
+
+Before a numeric observability profile is activated, the safe defaults are:
+
+- no packet, request, connection, or storage-access log;
+- no automatic remote logging or telemetry;
+- no public metrics endpoint and no host-published Prometheus endpoint;
+- no OpenTelemetry auto-instrumentation, trace ID, or span ID;
+- no automatic crash upload or support bundle;
+- core dumps, process-memory capture, and production debug mode disabled;
+- bounded volatile local summary only;
+- observer submission and public publication disabled;
+- generic application errors reduced to local fixed failure classes;
+- remote errors remain coarse and non-amplifying under the owning protocol.
+
+A deployment is not permitted to replace these defaults with a generic log
+shipper, service-mesh tracer, application performance monitor, or container
+log collector and still claim the same profile.
+
+## 8. Role-Local Window Model
+
+One role creates exactly one collector for each coarse window. It may update:
+
+- a fixed unsigned counter for an allowlisted count metric;
+- a fixed level bucket for queue, age, latency, ratio, or capacity state;
+- a fixed health value for consensus, clock, key, replay, or cover state;
+- one internal activity counter used only for the suppression decision.
+
+All counters saturate on overflow. They never wrap. The collector holds no
+identifiers, timestamps, strings, samples, exemplars, or per-peer maps.
+
+Sealing is irreversible and happens once. It produces:
+
+- one local report for every role;
+- one delayed observer report only for an online reporting role;
+- no observer report for Composer, observer, or FOG-SX roles.
+
+The role then discards its exact counters. A retry of IF-11 transmits the same
+sealed aggregate object according to the future command-specific retry rule;
+it does not reopen or recount the window.
+
+Discarding collector references is best-effort data minimization. The Go
+runtime, allocator, swap, hibernation, crash capture, and host may retain
+copies, so deployment controls remain necessary and complete erasure is not
+claimed.
+
+## 9. Structural Report Schema
+
+The in-process structural report contains only:
+
+| Field | Meaning | Restriction |
+| --- | --- | --- |
+| `schema_version` | report schema version | fixed to version 1 |
+| `profile_id` | authenticated observability profile | nonzero and consensus-authorized before activation |
+| `scope` | `local` or `observer` | fixed enum |
+| `role` | reporting security role | fixed enum, not node identity |
+| `window_id` | coarse aligned window | no event time |
+| `release_after_window` | earliest observer processing/release boundary | observer scope only and later than source window |
+| `traffic_suppressed` | sensitive metrics are below threshold | fixed boolean, submission schedule remains constant |
+| `measurements` | ordered fixed catalog for role and scope | metric and value enums only |
+
+The JSON emitted by the Go conformance module is a local test and diagnostic
+representation, not the IF-11 wire encoding. Claim-bearing IF-11 requires a
+separate byte-exact bounded encoding and signature specification.
+
+An aggregate-signing key identifier, signature suite, and signature belong to
+the future authenticated IF-11 submission envelope. They are raw observer
+input, never report measurements or public dimensions. Exact signing is not
+defined until the PKI and observability suites select an encoding and
+primitive.
+
+## 10. Value Vocabulary
+
+Count metrics use only:
+
+- `zero`;
+- `low`;
+- `medium`;
+- `high`;
+- `saturated`;
+- `suppressed` when traffic-sensitive activity is below threshold.
+
+Level metrics use only:
+
+- `unknown`;
+- `empty`;
+- `low`;
+- `medium`;
+- `high`;
+- `full`;
+- `suppressed` when traffic-sensitive activity is below threshold.
+
+Health metrics use only:
+
+- `unknown`;
+- `healthy`;
+- `degraded`;
+- `unavailable`.
+
+Bucket boundaries are part of one signed profile. Operators cannot customize
+them per node. Public documentation states the boundaries and their privacy
+rationale after activation.
+
+## 11. Metric Catalog
+
+The structural catalog is intentionally small. `Public eligible` means only
+that a future observer may consider the metric after multi-reporter
+aggregation. It never authorizes direct publication of one report.
+
+| Metric | Kind | Roles | Maximum visibility | Traffic-sensitive |
+| --- | --- | --- | --- | --- |
+| `process_start` | count | all | local | no |
+| `process_stop` | count | all | local | no |
+| `process_restart` | count | all | operator | no |
+| `configuration_rejected` | count | all | operator | no |
+| `consensus_health` | health | online reporters | public eligible | no |
+| `clock_health` | health | online reporters | operator | no |
+| `key_lifecycle_health` | health | online reporters | operator | no |
+| `replay_database_health` | health | mix | operator | no |
+| `queue_occupancy` | level | data plane | operator | yes |
+| `handshake_completed` | count | online reporters | operator | yes |
+| `handshake_failure` | count | online reporters | operator | yes |
+| `connection_age` | level | online reporters | operator | yes |
+| `profile_operations` | count | data plane | operator | yes |
+| `padding_data_ratio` | level | data plane | public eligible | yes |
+| `kemsphinx_failure` | count | mix, courier | operator | yes |
+| `mix_latency` | level | mix | operator | yes |
+| `cover_scheduler_health` | health | data plane | public eligible | no |
+| `storage_success` | count | courier, store | public eligible | yes |
+| `storage_overload` | count | courier, store | public eligible | yes |
+| `storage_expiry` | count | store | public eligible | yes |
+| `storage_corruption` | count | store | public eligible | no |
+| `storage_repair` | count | store | public eligible | no |
+| `capacity` | level | all | operator | no |
+| `composer_boot` | count | Composer | local | no |
+| `composer_lock` | count | Composer | local | no |
+| `composer_integrity_failure` | count | Composer | local | no |
+| `composer_failure` | count | Composer | local | no |
+| `authority_validation_failure` | count | authority | operator | no |
+| `observer_submission_rejected` | count | observer | local | no |
+| `observer_publication_suppressed` | count | observer | local | no |
+
+Adding a metric, role, value, or visibility class is a protocol and threat-
+model change. It requires schema versioning, conformance tests, and
+differencing review. A runtime plugin cannot extend the catalog.
+
+## 12. Failure Classification
+
+Owning protocols map internal errors to the catalog before collection. Raw
+errors never cross the boundary. A coarse count such as
+`configuration_rejected`, `handshake_failure`, `kemsphinx_failure`, or
+`authority_validation_failure` does not encode:
+
+- remote endpoint;
+- exact parser or signature stage;
+- expected or observed bytes;
+- profile candidates;
+- stack, file, line, or subsystem path;
+- retry or connection identity.
+
+Where a protocol needs more than one failure class, it must add a small fixed
+enum to this specification. It cannot place an exception message into a label
+or diagnostic field.
+
+## 13. Window and Time Rules
+
+The active profile defines one origin and one duration. Roles derive:
+
+```text
+window_id = floor((trusted_time - profile_origin) / window_duration)
+```
+
+This calculation is illustrative until the exact time profile is selected.
+No event time is stored. Clock uncertainty beyond the profile bound changes
+`clock_health` and follows the owning protocol's fail-closed time policy.
+It does not cause a role to open shorter windows or emit immediate alerts.
+
+Window duration does not adapt to traffic volume. All reporting roles submit
+at the same declared schedule with bounded profile-defined scheduling
+behavior. Adaptive flush, inactivity flush, and event-triggered window close
+are forbidden.
+
+## 14. Suppression and Bucketing
+
+The profile defines an activity unit for every reporting role, one minimum
+activity threshold, and common bucket boundaries for compatible metric kinds.
+Exact activity is never included in the sealed report.
+
+If activity is below the threshold:
+
+- every traffic-sensitive position is present with `suppressed`;
+- non-traffic health and safety positions retain their bucketed value;
+- the role still emits its scheduled observer submission;
+- the public view emits no small-population inference about that role or
+ window.
+
+The suppression threshold is not an anonymity set size. It is one defense
+against direct low-volume disclosure. Simulation and trace analysis must show
+how it behaves under sparse use, outages, suppression attacks, and colluding
+operators.
+
+## 15. IF-11 Aggregate Submission
+
+IF-11 carries one versioned aggregate submission from one authorized online
+reporting role to `fog-observer`. It uses the mutually authenticated
+role-specific FOG-WIRE context and an aggregate-signing key that is separate
+from Noise, node identity, PKI vote, KEMSphinx, receipt, storage, and release
+keys.
+
+The final IF-11 definition must bind at least:
+
+- network and schema version;
+- observability profile;
+- reporting role and authenticated reporter key;
+- coarse window and earliest release window;
+- exact ordered fixed-shape aggregate body;
+- signature suite and purpose-separated signature.
+
+It must define exact size, padding, authentication, retry, replay, expiry,
+parser limits, and failure behavior. FOG-WIRE fragmentation does not authorize
+variable report geometry or arbitrary metric extensions.
+
+The observer rejects unknown fields, metrics, roles, profiles, values,
+duplicate positions, reordered positions, stale windows, early release,
+unauthorized signers, invalid signatures, and more than one accepted report
+from the same reporter and window. Remote failure remains coarse and
+non-amplifying.
+
+## 16. Observer Processing
+
+`fog-observer` maintains three separate stores:
+
+1. a bounded replay/deduplication index for accepted reporter windows;
+2. short-lived raw signed submissions required for aggregation and audit;
+3. derived operator and public aggregate windows.
+
+The stores use different access rights and retention. Raw submissions expire
+after the bounded processing and dispute interval. They are not copied into a
+general data lake, backup, search index, ticket, or dashboard cache.
+
+The observer never reads role log files, databases, queues, packet captures,
+or container output. It cannot instruct a role to raise verbosity. It has no
+credential accepted by data-plane, storage, authority-voting, or release
+interfaces.
+
+## 17. Operator View
+
+The protected operator view may show only delayed fixed-window buckets from
+metrics whose visibility is `operator` or `public eligible`. It may group by
+role and declared public topology class when the active policy permits.
+
+It does not expose:
+
+- reporter or node drill-down for traffic-sensitive metrics;
+- arbitrary time ranges or window overlap;
+- raw submissions or signature identifiers as chart dimensions;
+- correlation across roles, providers, links, or exact failure times;
+- downloadable event records;
+- queries parameterized by peer, route, connection, packet, or user input.
+
+Access is least privilege. Authentication and authorization failures are
+recorded only as coarse local observer counters. Viewing a dashboard cannot
+extend the underlying retention period.
+
+## 18. Public View and Differencing Defense
+
+A public aggregate requires all of the following:
+
+- the profile-defined minimum number of distinct authorized reporters;
+- the required operator-family and role grouping;
+- completion of the release delay;
+- non-overlapping source and publication windows;
+- bucketed output with no exact totals;
+- suppression for low activity, reporter loss, or unsafe composition;
+- one fixed set of published dimensions;
+- no arbitrary filters, range queries, or node drill-down;
+- review of adjacent releases for differencing and intersection leakage.
+
+Public series are not cumulative. If one group or window is suppressed, the
+observer must not publish another overlapping total from which it can be
+subtracted. A later merge may publish only when the merge rule was fixed in
+advance and every released view remains non-subtractable.
+
+Reporter arrival, rejection, absence, and signature metadata are never public
+dimensions. Public URLs, cache keys, ETags, and response timing must not vary
+by hidden raw reporter state beyond the fixed publication schedule.
+
+## 19. Local Retention and Access
+
+The default implementation keeps sealed local summaries in a bounded volatile
+ring. A role profile may instead authorize protected persistence only when it
+defines:
+
+- exact maximum window count and age;
+- owner and filesystem permissions;
+- encryption and key ownership where required;
+- atomic replacement and crash behavior;
+- deletion and backup exclusion;
+- manual export schema;
+- consequences of a compromised operator account.
+
+No local report is retained indefinitely. Rotation removes the oldest whole
+window. It does not compress old windows into cumulative history.
+
+The Composer stores any permitted summary inside its encrypted vault or
+volatile memory. It has no automatic remote diagnostic path. A manually
+exported Composer diagnostic contains only a newly created coarse report
+selected and previewed by the user, never the raw ring or vault objects.
+
+## 20. Crash and Support Policy
+
+Production profiles disable:
+
+- core dumps and process memory capture;
+- automatic panic, exception, or crash upload;
+- operating-system crash collection that includes role memory;
+- heap, goroutine, thread, profiler, packet, or syscall traces in support
+ artifacts;
+- automatic attachment of logs, configuration, environment, or database
+ files to tickets.
+
+A crash increments only a coarse failure bucket after safe restart when the
+owning state machine permits restart. Security-critical state such as replay,
+ratchet, consensus, storage, or anchor state still follows its own fail-closed
+recovery rules. Observability never authorizes bypass or state recreation.
+
+A manual support artifact uses a separate reviewed schema, shows the exact
+fields to the operator or Composer user before export, excludes raw local
+summaries by default, and has a fixed size and deletion policy.
+
+## 21. Debug and Test Builds
+
+Production artifacts contain no runtime switch that enables prohibited
+logging. Environment variables, signals, command-line flags, configuration
+files, remote administration, or observer requests cannot activate packet or
+event tracing.
+
+Conformance builds may emit verbose traces only when all of the following
+hold:
+
+- the build is distinctly labeled and rejected by production configuration;
+- all keys, packets, contacts, routes, and inputs are public synthetic
+ fixtures generated for the test;
+- the build cannot join a claim-bearing network;
+- traces remain outside release artifacts and support bundles;
+- tests prove that production builds omit the mode.
+
+## 22. Go Conformance Module
+
+`../observability/` follows a small library shape because future role code
+will import the contract, while the observer daemon and wire codec remain
+separate responsibilities.
+
+The module provides:
+
+- fixed `Role`, `Metric`, `Level`, `Health`, `Scope`, and value enums;
+- role and value-kind validation;
+- concurrency-safe saturating in-memory counters;
+- an explicit policy with no default constructor;
+- one-way collector sealing;
+- fixed-shape local and observer reports;
+- low-activity suppression;
+- delayed observer windows;
+- a concurrency-safe bounded volatile local ring;
+- deterministic JSON only for conformance and local diagnostics.
+
+It deliberately does not provide:
+
+- arbitrary labels, messages, attributes, exemplars, or strings;
+- exact timestamps, durations, sizes, counters, or samples in reports;
+- disk persistence or remote log transport;
+- OpenTelemetry, Prometheus, syslog, journald, or service-mesh adapters;
+- IF-11 decoding, signing, networking, observer aggregation, or public output;
+- a numeric production policy.
+
+The absence of those adapters is a security boundary, not an unfinished
+convenience layer.
+
+## 23. Conformance and Adversarial Tests
+
+Before an observability profile becomes claim-bearing, tests must prove:
+
+1. every role rejects every metric outside its catalog;
+2. every metric rejects the wrong value kind and unknown value;
+3. exact counters saturate and never wrap;
+4. sealing occurs once and exact counters are inaccessible afterward;
+5. local and observer shapes are fixed for role and profile across zero, low,
+ threshold, and high activity;
+6. low traffic produces `suppressed`, not a missing field or exact count;
+7. Composer and FOG-SX roles cannot produce observer submissions;
+8. observer reports cannot contain local-only fields;
+9. observer release is later than the source window and overflow fails;
+10. packet, message, trace, peer, route, capability, address, path, error, and
+ timestamp fields are absent from encoded reports;
+11. local retention is bounded and chronological after rotation;
+12. unknown, duplicate, reordered, stale, oversized, and trailing IF-11 input
+ fails before allocation or signature-dependent action;
+13. duplicate reporter windows and replay fail without changing public state;
+14. missing reporters, low populations, adjacent windows, and overlapping
+ queries cannot defeat suppression by differencing;
+15. observer loss cannot alter data-plane or consensus behavior;
+16. production binaries reject debug/test profiles and do not produce core
+ dumps or automatic support uploads;
+17. malformed or attacker-controlled values never reach log formatting;
+18. raw submissions expire and cannot be recovered from backups or dashboard
+ caches after the declared interval.
+
+The current Go module covers items 1 through 11 at the role-local contract
+boundary. IF-11, observer, deployment, and public-release tests remain gated
+on their exact implementations.
+
+## 24. Operational Alerts
+
+Alerts are delayed state conditions, not event notifications. Candidate alert
+classes include:
+
+- consensus `degraded` or `unavailable`;
+- clock `degraded` or `unavailable`;
+- replay database `unavailable`;
+- key lifecycle `degraded` or `unavailable`;
+- cover scheduler `degraded` or `unavailable`;
+- sustained capacity `high` or `full`;
+- sustained storage corruption or repair failure;
+- repeated configuration rejection or process restart buckets.
+
+The exact number of windows needed to alert is profile-defined. Alerts never
+contain a packet, peer, connection, route, request, error string, or event
+time. Immediate local safety shutdown remains the responsibility of the
+owning role and does not wait for an alert.
+
+## 25. Deployment Requirements
+
+A claim-bearing deployment must demonstrate:
+
+- container or service-manager logging cannot capture stdout/stderr event
+ streams from the role;
+- only fixed coarse startup failure output is possible before the collector;
+- core dumps and automatic crash collection are disabled effectively, not
+ only in source configuration;
+- observer credentials cannot access role state or another interface;
+- no host port exposes role metrics directly;
+- local summary storage and observer raw storage meet declared ownership,
+ permissions, capacity, backup, rotation, and deletion rules;
+- dashboard and API caches do not outlive source retention;
+- production configuration rejects unknown metrics, test profiles, and debug
+ modes;
+- clock failure, observer outage, low activity, and reporter loss preserve the
+ declared fail-closed and suppression behavior.
+
+## 26. Requirements Traceability
+
+| Requirement | Observability response |
+| --- | --- |
+| `TM-OPS-01` | closed schema, forbidden data classes, coarse windows, suppression, delayed aggregation, bounded retention |
+| `TM-NET-01` | no fine timing, event stream, route, peer, or cross-role trace identifiers |
+| `TM-NET-03` | cover health, fixed reporting schedule, low-activity suppression, no weakened fallback |
+| `TM-ROLE-01` | role-local collectors and keys, no universal log access |
+| `TM-ROLE-02` | no packet, replay-tag, route, delay, or next-hop records |
+| `TM-ROLE-03` | no request, selection, receipt, storage, or per-source histories |
+| `TM-AVAIL-01` | saturating counters, bounded rings, fixed catalogs, bounded submissions |
+| `ARC-001` | separate role collectors, observer, state, access, and reporting keys |
+| `ARC-007` | one owner for local summaries and aggregate-signing material |
+| `ARC-008` | fixed schema, no dynamic labels, bounded windows and retention |
+| `ARC-009` | observability never authorizes a privacy-weakening recovery path |
+| `IF-11` | delayed authenticated fixed-shape aggregate only |
+
+## 27. Open Activation Decisions
+
+Before enabling IF-11 or public output, FOG must select and validate:
+
+- window origin and duration;
+- activity unit and minimum activity per reporting role;
+- count, level, latency, ratio, age, queue, and capacity bucket boundaries;
+- minimum independent reporters and operator-family diversity per public
+ group;
+- role-to-observer delay, observer-to-public delay, and merge behavior;
+- local, raw observer, derived operator, public, cache, and backup retention;
+- the exact IF-11 body encoding, fixed size, padding, signature suite, key
+ certification, replay, retry, and expiry rules;
+- public dimensions and anti-differencing composition analysis;
+- clock-uncertainty behavior and fixed submission scheduling;
+- deployment-specific storage, access, deletion, and crash controls;
+- simulation and trace evidence for sparse traffic, outages, reporter loss,
+ malicious suppression, collusion, and long-term intersection;
+- independent privacy and implementation review.
+
+Until those decisions are activated through signed profiles and evidence, the
+safe deployment state remains local bounded summaries only, with observer and
+public export disabled.
+
+## 28. References
+
+- FOG threat model: `FOG-THREAT-MODEL.md`
+- FOG architecture: `FOG-ARCHITECTURE.md`
+- FOG adjacent-link protocol: `FOG-WIRE.md`
+- FOG KEMSphinx profiles: `FOG-SPHINX-PROFILES.md`
+- FOG storage: `FOG-STORAGE.md`
+- FOG Composer: `FOG-COMPOSER.md`
+- FOG simulation: `FOG-SIMULATION.md`