# 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`
