Phase 2 — Runtime Engine Scope

Phase 1 (built) renders the 21-model schema as an AI-Safe CRUD register: tenants, layers, features, evaluation runs, relationships, rules, events, deliveries, disclosures, transfers, audit and reconciliation — browsable, with a dashboard. But the states are static: the seed shows an overlap already detected, an event already raised, a disclosure already sent. Nothing is computed, triggered or enforced by the system.

Phase 2 is the runtime that makes it live — running the spatial engine over geometries, evaluating rules, firing triggers and events, enforcing disclosure boundaries, delivering transfers and reconciling cross-tenant state. Same shape as the (built, cluster-proven) orchestrator engine, but with a geometry engine at its core.

Everything below is drawn from the pack's config/ (spatial_engine, triggers, orchestrator) and rules/ (spatial_rules, disclosure_profiles, event_templates). It is a scope, not a design.


A. The spatial engine

The headline. On a feature change (or a scheduled sweep), a SpatialEvaluationRun computes geometric relationships between candidate features:

  • Candidate selection by bbox/tenant/layer, then exact predicate — intersects, within, contains, touches, crosses, overlaps, near (distance) — writing/updating SpatialRelationships with overlap_area_m2 / distance_m.
  • Relationship lifecycle: new → confirmed → changed → ceased/resolved, with the timestamps the model already carries (first_detected_at, last_confirmed_at, ceased_at…).
  • The run records candidate_count / match_count / metrics — the demo's EVAL-2026-0007.

Decisions: the geometry library (Shapely/PostGIS), the CRS handling (default_crs), the near-distance threshold, incremental vs full re-evaluation.

B. Rules → triggers → events

SpatialRule matches a layer-pair + relationship type at a severity; a matched relationship, against a TriggerDefinition (watched events + actions), raises a SpatialEvent:

  • The demo: TENEMENTS overlaps PROTECTED (critical) → spatial.overlap.detected.
  • Event lifecycle open → acknowledged → closed; EventDelivery posts to each destination with idempotency (idempotency_key) and retry (attempt_count).

Decisions: rule evaluation order/precedence; event de-duplication window; delivery backoff.

C. Tenancy & disclosure enforcement

The security core. Every read/share/disclosure is bounded by tenancy:

  • LayerShare sets the access level (metadata / geometry / read / export) another tenant has to a layer — the engine must never expose more than the share grants.
  • A DisclosureProfile (geometry policy none/centroid/simplified/full + field allow/deny lists) governs what a cross-tenant disclosure actually contains; a disclosure that would exceed it is blocked or down-resolved (e.g. full geometry → centroid).
  • Permission scopes (tenant/layer/feature) gate user actions.

Decisions: how geometry is simplified/generalised; whether disclosure is push or pull; consent.

D. Data transfer & audit

A disclosure or export becomes a DataTransfer (direction, format, record count, checksum, payload ref) delivered to the destination; every material action writes an AuditEvent (with before/after state and context). This is the defensible record of what was shared with whom.

E. Reconciliation

ReconciliationCheck verifies that shared/disclosed state stays consistent across tenants — e.g. the overlap relationship is present and equivalent on both sides after disclosure — flagging an exception_code when it drifts. This is what keeps two tenants' views of a shared boundary honest.

F. Orchestrator integration

config/orchestrator.yaml maps spatial events to the Orchestrator: a mining-lease/protected-area overlap here can drive a downstream compliance workflow in another app. Delivery is the same outbox pattern as the rest of the suite.


How it would be built

  1. A spatial engine service (A) with a real geometry library — the app's defining capability.
  2. The rule/trigger/event pipeline (B) on top of it, reusing the orchestrator event contracts.
  3. Tenancy + disclosure enforcement (C) — the non-negotiable isolation guarantees, tested adversarially.
  4. Transfer/audit + reconciliation (D, E) and Orchestrator wiring (F).
  5. Tests from the pack's tests/access_matrix.yaml (who-can-see-what) and the demo overlap — ready-made.

Suggested sequencing

  1. Spatial engine (A) — makes relationships real; everything else depends on it.
  2. Rules → events (B) — turns geometry into actionable signals.
  3. Tenancy & disclosure enforcement (C) — the security core; gate before you share.
  4. Transfer/audit + reconciliation (D, E) — the defensible cross-tenant record.
  5. Orchestrator integration (F) — drive downstream workflows.

Each slice is independently shippable and demoable. The orchestrator (built and run live this session) is the working template for the event pipeline, delivery and tests.