## Status

Draft

## Story

**As a** platform integrator and SIEM/observability owner,
**I want** each log event to be wrapped in a schema-versioned JSON envelope,
**so that** downstream consumers can rely on a stable, evolvable structure across library upgrades.

## Acceptance Criteria

1. Define `LogEnvelope v1.0` with required top-level fields:
   - `schema_version: string` (e.g., "1.0")
   - `log: object`
2. `log` object minimum fields:
   - `timestamp: string (RFC3339 UTC) or float (POSIX seconds)` — pick one and document; prefer RFC3339 for readability
   - `level: string`
   - `message: string`
   - `context: object`
   - `diagnostics: object`
     Optional documented fields: `tags: array[string]`, `span_id: string`, `trace_id: string`, `logger: string`.
3. All built-in sinks (`stdout_json`, `rotating_file`) emit JSONL lines using `LogEnvelope v1.0`.
4. Backward-compatibility policy documented: additive → minor (e.g., 1.1); breaking → major (2.0) with migration notes.
5. Feature flag for strict envelope mode vs best-effort mode:
   - Strict: reject emission (record diagnostics) if envelope cannot be produced
   - Best-effort: fall back to safe serialization and record diagnostics
6. Property-based tests validate invariants; JSON Schema validates emitted events.
7. Add `jsonschema/log_envelope_v1.json` and use it in tests.

## Tasks / Subtasks

- [ ] Schema and documentation
  - [ ] Add `jsonschema/log_envelope_v1.json` capturing required/optional fields and type constraints (AC: 1, 2, 7)
  - [ ] Document envelope and versioning policy near serializer (AC: 4)
- [ ] Serialization plumbing
  - [ ] Create `serialize_envelope(log: Mapping[str, Any]) -> SerializedView` in `src/fapilog/core/serialization.py` or new `envelope.py` to build `{ "schema_version": "1.0", "log": {...} }` (single code path) (AC: 3, 5)
  - [ ] Choose timestamp format (RFC3339) and add helper to normalize from numeric inputs (AC: 2)
  - [ ] Add strict/best-effort toggle to settings (`core.strict_envelope_mode: bool = False`) (AC: 5)
  - [ ] Ensure `core.diagnostics.warn` records envelope fallback/strict failures (AC: 5)
- [ ] Sinks integration
  - [ ] Update `stdout_json` and `rotating_file` sinks to consume enveloped payloads (AC: 3)
  - [ ] Ensure zero-copy path remains via `serialize_mapping_to_json_bytes` and JSONL conversion (AC: 3)
- [ ] Tests
  - [ ] Property-based tests with `hypothesis` for required keys and type invariants (AC: 6)
  - [ ] Golden-file tests for stable shapes
  - [ ] JSON Schema validation using `jsonschema` or `fastjsonschema` (AC: 7)
  - [ ] Negative tests for strict mode behavior and diagnostics (AC: 5)
- [ ] Docs
  - [ ] README section with example envelope and versioning policy; short parsing example (AC: 4)

## Dev Notes

- Centralize envelope serialization to avoid divergence between sinks; sinks should receive pre-enveloped mappings.
- Existing serializers in `src/fapilog/core/serialization.py` support zero-copy JSON and JSONL; extend with a small helper to wrap the log mapping into the envelope prior to serialization.
- Timestamps: prefer RFC3339 string (UTC) for readability; provide a converter from existing POSIX `float` if needed (`core/events.py` uses POSIX by default) and document the choice in the schema.
- Keep `context` and `diagnostics` free-form but bounded by existing size/recursion limits.

### Testing

- Locations:
  - Unit: `tests/unit/envelope/`
  - Integration: alongside sink tests or `tests/integration/envelope/`
- Async sinks use `pytest.mark.asyncio`.
- Include concurrency/batching tests to ensure per-event envelope integrity is preserved.

## Change Log

| Date       | Version | Description                                         | Author    |
| ---------- | ------- | --------------------------------------------------- | --------- |
| 2025-08-15 | 0.2     | Clarified schema, timestamp choice, settings toggle | Architect |

## Dev Agent Record

### Agent Model Used

{{agent_model_name_version}}

### Debug Log References

### Completion Notes List

### File List

## QA Results


