Skip to content

feat(eventing): add typed signal-to-event projection architecture - #363

Draft
robbiemu wants to merge 15 commits into
MapleTechLabs:mainfrom
robbiemu:codex/issue-222-alerting-core
Draft

feat(eventing): add typed signal-to-event projection architecture#363
robbiemu wants to merge 15 commits into
MapleTechLabs:mainfrom
robbiemu:codex/issue-222-alerting-core

Conversation

@robbiemu

@robbiemu robbiemu commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR introduces a host-neutral typed signal-to-event projection architecture and a durable named-consumer boundary for Maple Local.

It separates three concerns:

  • source adapters normalize authenticated input into typed signals;
  • bounded selectors and pure versioned projectors create deterministic CloudEvents; and
  • Maple Local stages, commits, leases, acknowledges, checkpoints, and prunes projected events durably.

It also extracts the scheduled-alert decision and delivery policy into a reusable host-neutral package while preserving existing alert behavior.

Related to #222.

Event paths

Immediate per-occurrence path

authenticated input → source adapter → typed normalized signal → bounded selector → pure projector → durable outbox

The original telemetry continues through the existing warehouse encoder. A matched event is staged before the warehouse write and marked ready only after that write succeeds. Retrying the same source occurrence recomputes the same event identity.

Scheduled aggregate path

warehouse query → observation → alert lifecycle evaluation → factual alert event → existing delivery outbox

Rates, thresholds, percentiles, absence, recovery, flap suppression, and renotification remain scheduled conclusions over a window. They are not modeled as individual ingest-time facts.

Core architecture

A source definition publishes a typed field catalog, including allowed operators, sensitivity, and replay capability. Projection configuration stores a bounded typed predicate AST.

Projection revisions compile into immutable registry snapshots only after source fields, operators, activation time, and closed projector configuration are validated. Evaluation runs every matching projection from one snapshot and isolates failures so one malformed projector does not suppress successful siblings.

Projectors are pure, versioned functions. They declare an ID/version, accepted source kinds, output type/schema, and closed configuration decoder. They perform no I/O or external side effects.

Canonical CloudEvents and identity

Projected events use a common versioned CloudEvents envelope.

Event IDs are SHA-256 hashes over a length-delimited tuple of tenant, source kind, source, source occurrence ID, projection ID, and projection revision. Two optional backward-compatible extensions expose source occurrence identity and its quality. Historical envelopes without those extensions remain valid.

This lets downstream consumers correlate source occurrence → immutable Maple event → deterministic transport transaction without parsing event data.

Durable Local outbox and consumers

Maple Local stores projection revisions, active pointers, bounded failures, staged/ready events, and consumer state in a private SQLite control database.

Named consumers support:

  • explicit registration at the beginning or current tail;
  • whole-batch claims under bounded leases;
  • exact acknowledgement;
  • replay after lease expiry;
  • rejection of stale, wrong, or partial acknowledgements; and
  • pruning only through the lowest active-consumer acknowledgement.

Staged events are never pruned. Ready ordering is stable across restart and schema migration. Checkpoint manifests bind the control snapshot alongside the existing data backup.

Alert-core extraction

The new alerting-core package owns host-neutral observation evaluation, trigger/resolve/renotify planning, flap suppression, no-data recovery safety, scheduling helpers, delivery idempotency, and bounded retry policy.

Existing alert queries, persistence, queue behavior, and delivery payloads remain compatible. The factual event envelope is additive.

Existing producer convergence

The existing verified provider-webhook path now creates its factual event through the common projection seam while retaining queue compatibility, including jobs queued before deployment.

This demonstrates the architecture without making any provider-specific vocabulary part of the projection core.

Safety and boundedness

The implementation enforces:

  • bounded predicate depth, clause count, and string-literal bytes;
  • exact scalar typing without implicit coercion;
  • bounded CloudEvent size and schema validation;
  • immutable revision identity;
  • source/tenant isolation;
  • bounded low-cardinality telemetry; and
  • no payloads, URLs, credentials, identifiers, or arbitrary field values in eventing metrics.

Deliberate boundaries

This PR does not:

  • add a provider-specific lifecycle vocabulary or projector family;
  • implement transport delivery, destination topology, or agent policy;
  • add environment-specific paths, destination identities, credentials, or deployment configuration;
  • make projectors call external providers;
  • add a required broker;
  • replace scheduled aggregate alerts with ingest selectors;
  • expose arbitrary SQL or executable projection configuration;
  • claim exactly-once external side effects; or
  • activate projections automatically.

Provider adapters, deployment policy, transport delivery, and live credentials remain separate integrations built on the generic contracts introduced here.

Review guide

Primary surfaces:

  • packages/eventing-core: typed model, predicates, source/projector registries, deterministic identity, schemas, and fixtures;
  • packages/alerting-core: alert evaluation, lifecycle planning, idempotency, scheduling, and retry policy;
  • apps/cli/src/server/eventing: source-neutral normalization, telemetry, runtime, SQLite state, outbox, and consumer protocol;
  • apps/cli/src/server/serve.ts: decode-once integration and authenticated control/consumer endpoints;
  • apps/cli/src/server/checkpoints.ts: eventing-control checkpoint participation;
  • hosted alert services and the existing provider-webhook runtime; and
  • docs/local-event-consumers.md and docs/signal-to-event-projection.md.

Validation

Against the clean provider-neutral tree:

  • 64 focused tests pass across alerting core, eventing core, Local runtime, ingest, and consumer-control suites;
  • generated-schema and checkpoint compatibility are covered;
  • migration, restart, lease expiry, stale acknowledgement, pruning, and snapshot restore are exercised;
  • existing provider queue compatibility and alert behavior remain covered; and
  • git diff --check passes.

@robbiemu robbiemu changed the title refactor(alerting): extract a host-neutral alert core feat(eventing): add typed signal-to-event projection architecture Aug 8, 2026
@robbiemu
robbiemu force-pushed the codex/issue-222-alerting-core branch from 6fb2377 to 2f5ac1c Compare August 11, 2026 22:35
@robbiemu
robbiemu force-pushed the codex/issue-222-alerting-core branch from 2f5ac1c to 0212b99 Compare August 11, 2026 22:40
@robbiemu

Copy link
Copy Markdown
Contributor Author

I now have a working, mostly tested and verified version of this. Just putting a final review / finishing touches on it

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