Skip to content

feat: event stream promotion gates — record-framed commit log with SHA-384 integrity - #6

Merged
SWORDIntel merged 1 commit into
mainfrom
feat/event-stream-promotion-gates
Aug 11, 2026
Merged

feat: event stream promotion gates — record-framed commit log with SHA-384 integrity#6
SWORDIntel merged 1 commit into
mainfrom
feat/event-stream-promotion-gates

Conversation

@SWORDIntel

Copy link
Copy Markdown
Owner

Summary

Upgrades the QIHSE event stream from a 142-line raw mmap append log to a record-framed commit log passing all 9 promotion gates from TGMap's native analytics storage boundary (docs/NATIVE_ANALYTICS_STORAGE.md).

Record framing

  • 88-byte qihse_es_record_header_t: magic, format version, flags, schema_id, monotonic stream_offset, payload_size, prev_record_offset, SHA-384 event_id
  • Length-delimited records with stable identity and monotonic offsets

Durability

  • qihse_es_durability_t enum: NONE / FDATASYNC / FULL
  • Two-phase commit: write uncommitted header+payload → fdatasync → flip committed flag → fdatasync

Recovery

  • qihse_event_stream_replay() walks committed records via callback
  • qihse_event_stream_truncate_torn_tail() removes uncommitted tail via ftruncate
  • validate_header() detects bad magic, version, offset, payload_size

Security

  • O_NOFOLLOW symlink protection, 0600 owner-only permissions
  • topic_is_safe() rejects path traversal (.. and /)
  • flock(LOCK_EX) serializes concurrent writers, LOCK_SH for readers

Integrity

  • SHA-384 event ID via OpenSSL EVP: SHA-384(topic || payload)
  • Duplicate event-ID rejection (scans topic before append)
  • Compatible with TGMap evidence envelope

API surface

  • qihse_event_stream_open() with explicit durability + read-only mode
  • qihse_event_stream_append_record() with schema_id + event_id
  • qihse_event_stream_read() / iterate() / length() / has_event_id()
  • qihse_event_stream_replay() with callback
  • qihse_event_stream_truncate_torn_tail()
  • qihse_event_stream_flush()
  • Legacy qihse_event_stream_append() preserved (computes event_id internally)

Test plan

  • test_record_framing — length-delimited, schema, monotonic offset
  • test_owner_only_paths — file permissions are 0600
  • test_symlink_rejection — O_NOFOLLOW rejects symlink topics
  • test_durability_modes — fdatasync persists across restart
  • test_replay — all committed records replayed in order
  • test_torn_tail_recovery — uncommitted tail truncated
  • test_corruption_detection — bad magic stops replay
  • test_iteration — iterate all records in order
  • test_duplicate_rejection — second append with same event ID fails
  • test_sha384_integrity — event_id matches SHA-384(topic||payload)
  • test_permission_denied — read-only mode rejects writes
  • test_concurrent_writers — flock serializes appends
  • test_no_implicit_network — consume_zero_copy requires explicit fd
  • test_restart_recovery — all records survive close/reopen

Results: 49 assertions passed, 0 failed, 16 test cases total.

Build: gcc -std=c99 -Wall -Wextra -O2 -I./include -D_GNU_SOURCE tests/qihse_event_stream_test.c src/marmalade/qihse_event_stream.c -o test_event_stream -lcrypto && ./test_event_stream

Generated with Devin

… gates

Replace raw mmap append log with a record-framed commit log passing all 9
promotion gates from TGMap's native analytics storage boundary:

- 88-byte record headers (magic, format version, flags, schema_id,
  monotonic stream_offset, payload_size, prev_record_offset, SHA-384 event_id)
- Explicit durability modes (NONE / FDATASYNC / FULL) with checked fdatasync
- Two-phase commit: write uncommitted header+payload, fdatasync, flip
  committed flag, fdatasync
- Restart replay via callback, torn-tail recovery via ftruncate
- Corruption detection (bad magic/version/offset/payload_size)
- Duplicate event-ID rejection (SHA-384 of topic||payload)
- O_NOFOLLOW symlink protection, 0600 owner-only permissions
- topic_is_safe() rejects path traversal (.. and /)
- flock(LOCK_EX) serializes concurrent writers, LOCK_SH for readers
- Non-network local iteration by offset and cursor
- SHA-384 integrity via OpenSSL EVP (compatible with TGMap evidence envelope)
- Zero-copy sendfile consumption requires explicit fd (no implicit network)

API additions:
- qihse_event_stream_open() with durability + read-only mode
- qihse_event_stream_append_record() with schema_id + event_id
- qihse_event_stream_read() / iterate() / length() / has_event_id()
- qihse_event_stream_replay() with callback
- qihse_event_stream_truncate_torn_tail()
- qihse_event_stream_flush()

Tests: 16 test cases, 49 assertions, all passing. Covers record framing,
owner-only paths, O_NOFOLLOW, durability modes, replay, torn-tail recovery,
corruption detection, iteration, duplicate rejection, SHA-384 integrity,
read-only permission, concurrent writers, symlink rejection, no implicit
network, and restart recovery.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@SWORDIntel
SWORDIntel merged commit d7bebc5 into main Aug 11, 2026
1 check failed
@SWORDIntel
SWORDIntel deleted the feat/event-stream-promotion-gates branch August 11, 2026 22:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant