Skip to content

expansions: has no master-delete handler - a deleted master leaves orphaned or undeletable children #6821

Description

@delchev

Summary

expansions: binds the master's create and -updated events only - no handler exists for the master's delete. What happens to the generated child rows then depends on the schema: where the FK constraint is enforced, the master cannot be deleted at all (constraint violation -> 409) with no cleanup affordance; where it is not, the children survive as orphans referencing a master that no longer exists and keep feeding rollups and reports. Either way the expansion lacks a delete story.

Found by static source review against origin/master (1dc87fb505).

Where

  • GlueIntentGenerator.buildExpansions (2559-2560) - exactly two entries: OnCreate (suffix ``) and OnUpdate (`-updated`). No `-deleted`.
  • events/Expansion.java.template:30 - destination is the master's topic + suffix; no delete variant exists.
  • Schema note: the schema template DOES emit type: "foreignKey" structures for to-one relations (template-application-schema/.../application.schema.template), so the blocked-delete variant is the likely runtime outcome where constraints are applied. (The stale "no FK constraints at all" note in engine-intent/CLAUDE.md:394 should be corrected while here - only the table-level constraints object for multi-column unique keys is conditionally empty.)

Example

A leave request with generated day rows is deleted (or its delete is attempted). Outcome A: 409 with no way to remove the request short of manually deleting each day row first. Outcome B (no enforced constraint): orphaned day rows keep counting in balances and reports.

Proposed fix

Emit a -deleted handler that removes the generated children (the expansion already owns the child set by its own contract - "a span change replaces every child pointing at the master"). Alternatively lean on a database cascade for expansion-owned children specifically - but that is a schema-semantics decision with wider blast radius; the handler is the conservative fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions