Define canonical, tamper-evident audit-event schema and local query contract #487

Open
opened 2026-07-26 00:48:11 -04:00 by didericis-codex · 9 comments
Collaborator

Summary

Define one versioned audit-event contract used by every bot-bottle security and provenance producer, with a canonical append-only representation, tamper-evidence, useful local search, and a stable mapping to the centralized provenance stream.

Today the pieces are fragmented:

  • #468 proposes a host-controller-owned historical record, append-only JSONL, and hash chaining, but does not define the event structure.
  • #324 specifies webhook delivery, buffering/replay, authentication, and causal ordering, but not the payload schema.
  • #480 defines signed-commit attribution records, but only for that domain.
  • AuditEntry / supervise_audit_entries is specific to supervisor decisions and cannot represent lifecycle, egress, commit, forge, authentication, or host-controller events.

Without a shared contract, each producer will invent incompatible fields and integrity semantics, making local search, cross-host correlation, replay, and incident reconstruction unreliable.

Security requirement

The audit trail is security evidence, not ordinary diagnostic logging. An agent must not be able to choose or forge host-owned attribution fields, splice/reorder events undetectably, inject secrets into the record, or exploit differences between the local journal, local index, and exported representation.

This issue defines the contract; implementation may be split into follow-up PRs.

Proposed architecture

security/provenance producers
        |
        v
host-controller audit writer (#468)
        |-- canonical append-only JSONL journal (source of truth)
        |-- rebuildable SQLite query index (local search)
        `-- durable outbox/export cursor (#324)

The local audit must remain usefully searchable without the paid platform. The platform value is cross-host aggregation, off-box retention, correlation, alerting, RBAC, and compliance-oriented queries/exports.

Contract to specify

Versioned envelope

At minimum:

  • schema_version
  • globally unique event_id
  • stable event_type / event-name registry
  • event timestamp and observed timestamp
  • source component and host identity
  • bottle, bottled-agent, and activation identifiers where applicable
  • manifest digest and relevant policy/config version
  • actor, action, resource, outcome, and reason
  • correlation ID and causation/parent event ID
  • typed event-specific payload
  • sensitivity/redaction classification
  • integrity metadata (previous_hash, event_hash, chain/segment identity)

The specification must distinguish fields supplied by the host/control plane from untrusted claims copied from a bottle, gateway, forge, or remote response.

Canonicalization and integrity

Define:

  • canonical byte serialization used for hashing;
  • hash-chain construction and segment boundaries;
  • behavior across rotation, restart, import, and truncation;
  • duplicate/idempotency semantics;
  • ordering guarantees (at least strict causal order per activation/bottle);
  • verification tooling and failure behavior;
  • whether/when signatures supplement hash chaining.

Storage and local query

  • Canonical journal: one structured JSON event per line, append-only.
  • SQLite: derived/rebuildable index, not a second source of truth.
  • Define indexable fields and a minimum local CLI/API query surface, including filters for time, event type, host, bottle, activation, agent, outcome, repository, correlation ID, and commit SHA.
  • Define journal-to-index rebuild and corruption behavior.

Export/interoperability

  • Define the exact payload consumed by #324.
  • Map the envelope to the stable OpenTelemetry Logs data model and/or a CloudEvents JSON envelope without losing integrity or attribution semantics.
  • Preserve event IDs for deduplication and cursor replay.
  • Specify backpressure, acknowledgement, retry, and retention interaction at the contract level where #324 depends on it.

Initial event registry

Cover at least:

  • bottle lifecycle transitions;
  • host-controller/broker operations;
  • supervise proposal and operator decision;
  • egress request, policy decision, cutoff, and security anomaly;
  • git-gate decision and signed-commit attribution (#480);
  • forge-triggered work;
  • authentication/authorization failure;
  • audit-chain verification, truncation, or export failure.

Each type must document required attributes, which fields are trusted vs. claimed, redaction rules, and correlation behavior.

Acceptance criteria

  • A durable PRD or decision record defines the versioned envelope and initial event registry.
  • Canonical JSON serialization and hash-chain rules are unambiguous and covered by test vectors.
  • Trust provenance is explicit for every common field and event-specific attribute.
  • Redaction/sensitivity rules prohibit credentials, raw secrets, and unsafe payload capture by default.
  • The JSONL journal is the canonical source and the SQLite search index is fully rebuildable from it.
  • A minimum local search/query contract is specified.
  • #324 can transport/replay the format without inventing another envelope.
  • #480 signed-commit attribution maps into the common event contract without weakening its byte-to-activation-key guarantee.
  • Schema evolution and backward-compatible readers are specified.
  • Integrity verification detects modification, deletion/truncation, reordering, and invalid chain continuation to the extent promised by the threat model.

Dependencies / ordering

  • Builds on #468 for host-controller ownership of historical audit state.
  • Blocks the event-format portion of #324 and the audit-recording/storage portion of #480.
  • Feature-specific production work that does not persist/export audit events may proceed independently.

Non-goals

  • Building the paid centralized platform or its UI in this issue.
  • Defining pricing/retention tiers.
  • Treating ordinary stderr/debug logs as security audit evidence.
  • Capturing prompts, response bodies, credentials, or arbitrary traffic payloads by default.
## Summary Define one versioned audit-event contract used by every bot-bottle security and provenance producer, with a canonical append-only representation, tamper-evidence, useful local search, and a stable mapping to the centralized provenance stream. Today the pieces are fragmented: - #468 proposes a host-controller-owned historical record, append-only JSONL, and hash chaining, but does not define the event structure. - #324 specifies webhook delivery, buffering/replay, authentication, and causal ordering, but not the payload schema. - #480 defines signed-commit attribution records, but only for that domain. - `AuditEntry` / `supervise_audit_entries` is specific to supervisor decisions and cannot represent lifecycle, egress, commit, forge, authentication, or host-controller events. Without a shared contract, each producer will invent incompatible fields and integrity semantics, making local search, cross-host correlation, replay, and incident reconstruction unreliable. ## Security requirement The audit trail is security evidence, not ordinary diagnostic logging. An agent must not be able to choose or forge host-owned attribution fields, splice/reorder events undetectably, inject secrets into the record, or exploit differences between the local journal, local index, and exported representation. This issue defines the contract; implementation may be split into follow-up PRs. ## Proposed architecture ```text security/provenance producers | v host-controller audit writer (#468) |-- canonical append-only JSONL journal (source of truth) |-- rebuildable SQLite query index (local search) `-- durable outbox/export cursor (#324) ``` The local audit must remain usefully searchable without the paid platform. The platform value is cross-host aggregation, off-box retention, correlation, alerting, RBAC, and compliance-oriented queries/exports. ## Contract to specify ### Versioned envelope At minimum: - `schema_version` - globally unique `event_id` - stable `event_type` / event-name registry - event timestamp and observed timestamp - source component and host identity - bottle, bottled-agent, and activation identifiers where applicable - manifest digest and relevant policy/config version - actor, action, resource, outcome, and reason - correlation ID and causation/parent event ID - typed event-specific payload - sensitivity/redaction classification - integrity metadata (`previous_hash`, `event_hash`, chain/segment identity) The specification must distinguish fields supplied by the host/control plane from untrusted claims copied from a bottle, gateway, forge, or remote response. ### Canonicalization and integrity Define: - canonical byte serialization used for hashing; - hash-chain construction and segment boundaries; - behavior across rotation, restart, import, and truncation; - duplicate/idempotency semantics; - ordering guarantees (at least strict causal order per activation/bottle); - verification tooling and failure behavior; - whether/when signatures supplement hash chaining. ### Storage and local query - Canonical journal: one structured JSON event per line, append-only. - SQLite: derived/rebuildable index, not a second source of truth. - Define indexable fields and a minimum local CLI/API query surface, including filters for time, event type, host, bottle, activation, agent, outcome, repository, correlation ID, and commit SHA. - Define journal-to-index rebuild and corruption behavior. ### Export/interoperability - Define the exact payload consumed by #324. - Map the envelope to the stable OpenTelemetry Logs data model and/or a CloudEvents JSON envelope without losing integrity or attribution semantics. - Preserve event IDs for deduplication and cursor replay. - Specify backpressure, acknowledgement, retry, and retention interaction at the contract level where #324 depends on it. ### Initial event registry Cover at least: - bottle lifecycle transitions; - host-controller/broker operations; - supervise proposal and operator decision; - egress request, policy decision, cutoff, and security anomaly; - git-gate decision and signed-commit attribution (#480); - forge-triggered work; - authentication/authorization failure; - audit-chain verification, truncation, or export failure. Each type must document required attributes, which fields are trusted vs. claimed, redaction rules, and correlation behavior. ## Acceptance criteria - [ ] A durable PRD or decision record defines the versioned envelope and initial event registry. - [ ] Canonical JSON serialization and hash-chain rules are unambiguous and covered by test vectors. - [ ] Trust provenance is explicit for every common field and event-specific attribute. - [ ] Redaction/sensitivity rules prohibit credentials, raw secrets, and unsafe payload capture by default. - [ ] The JSONL journal is the canonical source and the SQLite search index is fully rebuildable from it. - [ ] A minimum local search/query contract is specified. - [ ] #324 can transport/replay the format without inventing another envelope. - [ ] #480 signed-commit attribution maps into the common event contract without weakening its byte-to-activation-key guarantee. - [ ] Schema evolution and backward-compatible readers are specified. - [ ] Integrity verification detects modification, deletion/truncation, reordering, and invalid chain continuation to the extent promised by the threat model. ## Dependencies / ordering - Builds on #468 for host-controller ownership of historical audit state. - Blocks the event-format portion of #324 and the audit-recording/storage portion of #480. - Feature-specific production work that does not persist/export audit events may proceed independently. ## Non-goals - Building the paid centralized platform or its UI in this issue. - Defining pricing/retention tiers. - Treating ordinary stderr/debug logs as security audit evidence. - Capturing prompts, response bodies, credentials, or arbitrary traffic payloads by default.
didericis-codex added the Kind/SecurityKind/Feature
Priority
Critical
1
labels 2026-07-26 00:48:11 -04:00
Owner

@didericis-codex debating whether all outbound requests should also be logged... there are probably better tools for that specifically, so leaning no, but would be kind of nice to have an all-in-one monitoring service built into bot bottle that could look at that. thoughts?

@didericis-codex debating whether all outbound requests should also be logged... there are probably better tools for that specifically, so leaning no, but would be kind of nice to have an all-in-one monitoring service built into bot bottle that could look at that. thoughts?
Author
Collaborator

I lean no for the canonical audit journal, yes as a separate telemetry stream that the same service can ingest and search.

“All outbound requests” has very different volume, privacy, retention, and integrity requirements from security audit evidence. Putting every allowed request in the permanent hash-chained journal would make the important events harder to find, increase disk/export cost, and create a new sensitive-data liability (URLs, query strings, headers, and bodies routinely contain secrets). It also encourages #487 to become an observability platform rather than a crisp audit contract.

I would split it into three levels:

  1. Always-on audit events: denied requests, DLP matches, credential-injection failures, policy changes, budget cutoffs, anomalous bypass attempts, and audit/telemetry pipeline failures. These belong in #487’s tamper-evident journal.
  2. Default aggregate telemetry: per bottle/route/provider/time bucket counts, bytes, latency, status classes, and authoritative token/cost usage where available. This is searchable locally and exportable, but has shorter retention and need not be one permanent event per request.
  3. Opt-in request access logs: method, normalized destination host, matched route ID, status, bytes, duration, and correlation ID. Disabled by default or enabled per bottle/route for incident response. Never record Authorization/cookies/injected credentials; omit bodies and raw query strings by default; enforce explicit retention limits.

The all-in-one monitoring experience can still be a strong bot-bottle/platform feature: one UI correlates audit events, egress telemetry, lifecycle, approvals, and signed commits. They do not need to share one storage/retention policy to appear in one timeline. Exporting access telemetry through OpenTelemetry also lets users send it to Loki/Elastic/Splunk/etc. instead of requiring us to outbuild dedicated log systems.

For #487, I would include an event class/sensitivity/retention field and reserve egress.request / egress.aggregate event shapes, but make the acceptance criterion only that security-relevant egress decisions enter the canonical audit chain. A separate issue should define full access logging, aggregation, redaction, sampling, and retention. That gives us the integrated product path without silently turning the audit log into packet surveillance.

I lean **no for the canonical audit journal, yes as a separate telemetry stream that the same service can ingest and search**. “All outbound requests” has very different volume, privacy, retention, and integrity requirements from security audit evidence. Putting every allowed request in the permanent hash-chained journal would make the important events harder to find, increase disk/export cost, and create a new sensitive-data liability (URLs, query strings, headers, and bodies routinely contain secrets). It also encourages #487 to become an observability platform rather than a crisp audit contract. I would split it into three levels: 1. **Always-on audit events:** denied requests, DLP matches, credential-injection failures, policy changes, budget cutoffs, anomalous bypass attempts, and audit/telemetry pipeline failures. These belong in #487’s tamper-evident journal. 2. **Default aggregate telemetry:** per bottle/route/provider/time bucket counts, bytes, latency, status classes, and authoritative token/cost usage where available. This is searchable locally and exportable, but has shorter retention and need not be one permanent event per request. 3. **Opt-in request access logs:** method, normalized destination host, matched route ID, status, bytes, duration, and correlation ID. Disabled by default or enabled per bottle/route for incident response. Never record Authorization/cookies/injected credentials; omit bodies and raw query strings by default; enforce explicit retention limits. The all-in-one monitoring experience can still be a strong bot-bottle/platform feature: one UI correlates audit events, egress telemetry, lifecycle, approvals, and signed commits. They do not need to share one storage/retention policy to appear in one timeline. Exporting access telemetry through OpenTelemetry also lets users send it to Loki/Elastic/Splunk/etc. instead of requiring us to outbuild dedicated log systems. For #487, I would include an event class/sensitivity/retention field and reserve `egress.request` / `egress.aggregate` event shapes, but make the acceptance criterion only that **security-relevant egress decisions** enter the canonical audit chain. A separate issue should define full access logging, aggregation, redaction, sampling, and retention. That gives us the integrated product path without silently turning the audit log into packet surveillance.
Owner

@didericis-codex for sure, should be different buckets. Let me explain my thought process for context.

Before going much further I want to make sure the bottlenecks we've created can give us the monitoring capabilities we need, and surface any potential issues with how we plan to record that monitoring data and make it comprehensive before we bolt on more features. Part of that logic is to make sure that we don't create any features that work against that comprehensive monitoring, which we'd detect earlier if it were implemented.

For traffic monitoring (and process monitoring in the future), I'm not sure if we really need to do anything/I think the bottleneck is already there. I think we could simply put another existing tool in the gateway egress for traffic monitoring. Process monitoring is a different story, but I think we could similarly use built in monitoring tools for firecracker, docker, and macos containers.

Given that I think we can probably skip the aggregate telemetry and request access logs for now.

Thoughts?

@didericis-codex for sure, should be different buckets. Let me explain my thought process for context. Before going much further I want to make sure the bottlenecks we've created can give us the monitoring capabilities we need, and surface any potential issues with how we plan to record that monitoring data and make it comprehensive before we bolt on more features. Part of that logic is to make sure that we don't create any features that work against that comprehensive monitoring, which we'd detect earlier if it were implemented. For traffic monitoring (and process monitoring in the future), I'm not sure if we really need to do anything/I think the bottleneck is already there. I think we could simply put another existing tool in the gateway egress for traffic monitoring. Process monitoring is a different story, but I think we could similarly use built in monitoring tools for firecracker, docker, and macos containers. Given that I think we can probably skip the aggregate telemetry and request access logs for now. Thoughts?
Author
Collaborator

Yes — I think that is the right scope. We do not need to build aggregate telemetry or request access logs now. We need to make sure the architecture does not foreclose them and that the bottlenecks really cover what we think they cover.

For traffic, the gateway is already the right observation point provided the network invariant is true: all permitted application egress traverses it, and anything that does not traverse it is blocked. I would document/test that invariant and enumerate intentional exceptions (DNS plumbing, host-controller traffic, backend management links, etc.). Then a future collector can be inserted at the gateway without changing bottle-facing APIs.

The one design hazard worth surfacing now is placement relative to credential injection. The gateway inserts real provider/forge credentials that the bottle never sees. A generic traffic monitor placed after injection—or a packet-capture tool on the wrong interface—could turn the monitoring store into a credential leak. Future monitoring must either observe before secret injection, collect metadata only, or have a strict redaction boundary owned by trusted code. We should preserve an explicit hook/location for that rather than assuming any off-the-shelf gateway monitor is safe.

The other readiness invariants I would capture now are:

  • stable host/bottle/activation IDs supplied by trusted infrastructure, so traffic cannot be mislabeled by the agent;
  • a control-plane export path, with no writable audit/monitoring database mounted into the data plane;
  • defined behavior under collector failure/backpressure (monitoring failure must neither silently open egress nor wedge normal traffic unless explicitly configured fail-closed);
  • timestamps/correlation IDs sufficient to join future traffic observations to lifecycle and audit events;
  • a documented coverage boundary: HTTP(S) visibility is not automatically DNS, raw sockets, local VM traffic, or process activity.

Process monitoring can remain a later backend-specific adapter problem. Firecracker, Docker, and Apple containers expose different primitives; we should normalize their output only when there is a concrete use case, rather than inventing an abstraction now.

So my recommendation is: skip traffic/process telemetry implementation for now, keep #487 focused on the canonical security audit contract, and add only observability-readiness invariants/tests where upcoming architecture work could accidentally create a bypass or expose injected secrets. An existing monitoring tool can be evaluated later against those invariants.

Yes — I think that is the right scope. We do not need to build aggregate telemetry or request access logs now. We need to make sure the architecture does not foreclose them and that the bottlenecks really cover what we think they cover. For traffic, the gateway is already the right observation point **provided the network invariant is true**: all permitted application egress traverses it, and anything that does not traverse it is blocked. I would document/test that invariant and enumerate intentional exceptions (DNS plumbing, host-controller traffic, backend management links, etc.). Then a future collector can be inserted at the gateway without changing bottle-facing APIs. The one design hazard worth surfacing now is **placement relative to credential injection**. The gateway inserts real provider/forge credentials that the bottle never sees. A generic traffic monitor placed after injection—or a packet-capture tool on the wrong interface—could turn the monitoring store into a credential leak. Future monitoring must either observe before secret injection, collect metadata only, or have a strict redaction boundary owned by trusted code. We should preserve an explicit hook/location for that rather than assuming any off-the-shelf gateway monitor is safe. The other readiness invariants I would capture now are: - stable host/bottle/activation IDs supplied by trusted infrastructure, so traffic cannot be mislabeled by the agent; - a control-plane export path, with no writable audit/monitoring database mounted into the data plane; - defined behavior under collector failure/backpressure (monitoring failure must neither silently open egress nor wedge normal traffic unless explicitly configured fail-closed); - timestamps/correlation IDs sufficient to join future traffic observations to lifecycle and audit events; - a documented coverage boundary: HTTP(S) visibility is not automatically DNS, raw sockets, local VM traffic, or process activity. Process monitoring can remain a later backend-specific adapter problem. Firecracker, Docker, and Apple containers expose different primitives; we should normalize their output only when there is a concrete use case, rather than inventing an abstraction now. So my recommendation is: **skip traffic/process telemetry implementation for now**, keep #487 focused on the canonical security audit contract, and add only observability-readiness invariants/tests where upcoming architecture work could accidentally create a bypass or expose injected secrets. An existing monitoring tool can be evaluated later against those invariants.
Owner

stable host/bottle/activation IDs supplied by trusted infrastructure, so traffic cannot be mislabeled by the agent;

Yep, bottled agent ids should be assigned by the orchestrator registry, and audit events should occur before we use them.

a control-plane export path, with no writable audit/monitoring database mounted into the data plane

This is the part I was debating about just implementing now/maybe normalizing to our own shape for a future all in one service... It should be pretty simple. Would probably just want to shove some existing tool which spits out the requests (and responses?) from the mitmproxy to the control-plane.

defined behavior under collector failure/backpressure (monitoring failure must neither silently open egress nor wedge normal traffic unless explicitly configured fail-closed);

Don't want to deal with this now, but should probably just be a write only spigot/no ack by default, maybe with some kind of ack behavior you could turn on to ensure no egress logs are dropped

timestamps/correlation IDs sufficient to join future traffic observations to lifecycle and audit events;

Timestamps and bottled agent ids should probably be sufficient.

a documented coverage boundary: HTTP(S) visibility is not automatically DNS, raw sockets, local VM traffic, or process activity.

Yeah, only HTTP(S) for now (and no deep request monitoring when inspect is off)

> stable host/bottle/activation IDs supplied by trusted infrastructure, so traffic cannot be mislabeled by the agent; Yep, bottled agent ids should be assigned by the orchestrator registry, and audit events should occur before we use them. > a control-plane export path, with no writable audit/monitoring database mounted into the data plane This is the part I was debating about just implementing now/maybe normalizing to our own shape for a future all in one service... It should be pretty simple. Would probably just want to shove some existing tool which spits out the requests (and responses?) from the mitmproxy to the control-plane. > defined behavior under collector failure/backpressure (monitoring failure must neither silently open egress nor wedge normal traffic unless explicitly configured fail-closed); Don't want to deal with this now, but should probably just be a write only spigot/no ack by default, maybe with some kind of ack behavior you could turn on to ensure no egress logs are dropped > timestamps/correlation IDs sufficient to join future traffic observations to lifecycle and audit events; Timestamps and bottled agent ids should probably be sufficient. > a documented coverage boundary: HTTP(S) visibility is not automatically DNS, raw sockets, local VM traffic, or process activity. Yeah, only HTTP(S) for now (and no deep request monitoring when inspect is off)
Author
Collaborator

That all sounds directionally right. I would keep the implementation deliberately small if you do it now: a mitmproxy addon emits a normalized, metadata-only flow record to a control-plane ingestion endpoint. Do not forward the raw mitmproxy flow object and do not treat this as the canonical audit writer.

A few boundaries I would keep explicit:

  • Request + response metadata, not contents. Request side gives start time, method, normalized host, matched route/policy, bottle/activation, and inspection mode. Response side completes status, duration, bytes, and provider usage where available. No headers, cookies, query values, injected credentials, or bodies in the generic record. Provider-specific usage parsing can remain separate.
  • Extract after policy resolution but before serialization. The addon may internally see injected credentials depending on hook ordering; the serializer should construct an allowlisted DTO field-by-field so secrets cannot accidentally ride along. This matters more than which mitmproxy hook technically emits it.
  • Fire-and-forget is fine only for telemetry. A write-only, no-ack spigot with drops counted/logged is a reasonable default for optional access telemetry. Security audit events from #487 need durable acceptance/outbox semantics; otherwise an attacker or outage can erase precisely the evidence we care about. An optional acknowledged telemetry mode can come later.
  • Use activation ID plus a per-flow ID. Bottle ID + timestamp is enough for rough dashboards, but not reliable correlation when requests are concurrent, retried, or a bottle identity is reused across activation/restart boundaries. The gateway can generate one opaque flow ID and use it for the request/response pair; the orchestrator supplies the activation identity from trusted registry state. For centralized use, host ID is also needed, since bottle IDs are not necessarily globally unique.
  • Inspection-off contract: agreed—HTTP(S) only. When TLS inspection is off, record only what the gateway actually knows safely (for example destination/CONNECT metadata and byte/timing totals), and mark inspection_mode/visibility explicitly so absence of method/status is not mistaken for missing data.

On lifecycle ordering, yes: allocate/register the bottled-agent + activation IDs first, append the lifecycle/audit event that establishes them, then permit launch/traffic that references them.

If implemented now, I would still put the telemetry spigot in a small separate issue/PR from #487. #487 can define the shared envelope dimensions and trust labels; the spigot proves the choke point is usable without making request telemetry part of the permanent security-audit promise.

That all sounds directionally right. I would keep the implementation deliberately small if you do it now: a mitmproxy addon emits a **normalized, metadata-only flow record** to a control-plane ingestion endpoint. Do not forward the raw mitmproxy flow object and do not treat this as the canonical audit writer. A few boundaries I would keep explicit: - **Request + response metadata, not contents.** Request side gives start time, method, normalized host, matched route/policy, bottle/activation, and inspection mode. Response side completes status, duration, bytes, and provider usage where available. No headers, cookies, query values, injected credentials, or bodies in the generic record. Provider-specific usage parsing can remain separate. - **Extract after policy resolution but before serialization.** The addon may internally see injected credentials depending on hook ordering; the serializer should construct an allowlisted DTO field-by-field so secrets cannot accidentally ride along. This matters more than which mitmproxy hook technically emits it. - **Fire-and-forget is fine only for telemetry.** A write-only, no-ack spigot with drops counted/logged is a reasonable default for optional access telemetry. Security audit events from #487 need durable acceptance/outbox semantics; otherwise an attacker or outage can erase precisely the evidence we care about. An optional acknowledged telemetry mode can come later. - **Use activation ID plus a per-flow ID.** Bottle ID + timestamp is enough for rough dashboards, but not reliable correlation when requests are concurrent, retried, or a bottle identity is reused across activation/restart boundaries. The gateway can generate one opaque flow ID and use it for the request/response pair; the orchestrator supplies the activation identity from trusted registry state. For centralized use, host ID is also needed, since bottle IDs are not necessarily globally unique. - **Inspection-off contract:** agreed—HTTP(S) only. When TLS inspection is off, record only what the gateway actually knows safely (for example destination/CONNECT metadata and byte/timing totals), and mark `inspection_mode`/visibility explicitly so absence of method/status is not mistaken for missing data. On lifecycle ordering, yes: allocate/register the bottled-agent + activation IDs first, append the lifecycle/audit event that establishes them, then permit launch/traffic that references them. If implemented now, I would still put the telemetry spigot in a small separate issue/PR from #487. #487 can define the shared envelope dimensions and trust labels; the spigot proves the choke point is usable without making request telemetry part of the permanent security-audit promise.
Owner

@didericis-codex file details about the telemetry spigot in a new issue

@didericis-codex file details about the telemetry spigot in a new issue
Owner

@didericis-claude create a new PRD for this. We'll do this immediately after the host controller and wire these audit events into the host controller.

@didericis-claude create a new PRD for this. We'll do this immediately after the host controller and wire these audit events into the host controller.
Collaborator

Done — opened #495 with a draft PRD: Canonical tamper-evident audit-event schema and local query contract (docs/prds/prd-new-audit-event-schema.md).

It defines a single versioned AuditEvent envelope with a structural trusted/untrusted split, canonical-JSON + per-writer hash chain for tamper-evidence, an append-only JSONL journal as source of truth with a rebuildable SQLite index for local query, an initial event registry (lifecycle.* / decision.* / egress.* / auth.* / forge.*), and an enforced redaction rule.

Per your note, it's sequenced to land right after the host controller (#468) — the host controller is the first producer, emitting lifecycle.* through the new envelope, and the existing supervise/egress/git-gate/auth producers migrate behind it. Open questions (single-writer vs per-producer chains, clock/ordering across restarts, reject-vs-redact) are called out at the end for your feedback.

Done — opened #495 with a draft PRD: **Canonical tamper-evident audit-event schema and local query contract** (`docs/prds/prd-new-audit-event-schema.md`). It defines a single versioned `AuditEvent` envelope with a structural trusted/untrusted split, canonical-JSON + per-writer hash chain for tamper-evidence, an append-only JSONL journal as source of truth with a rebuildable SQLite index for local query, an initial event registry (`lifecycle.*` / `decision.*` / `egress.*` / `auth.*` / `forge.*`), and an enforced redaction rule. Per your note, it's sequenced to land right after the host controller (#468) — the host controller is the first producer, emitting `lifecycle.*` through the new envelope, and the existing supervise/egress/git-gate/auth producers migrate behind it. Open questions (single-writer vs per-producer chains, clock/ordering across restarts, reject-vs-redact) are called out at the end for your feedback.
Sign in to join this conversation.
3 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: didericis/bot-bottle#487