Skip to content

feat(contracts): publish inject trigger request and occurrence contracts (part of #1366) #1423

Closed

Description

@doublewhy

Gap Claim

ADR-112 accepted external-inject-occurrence/rev1 (EI-01–EI-06 in specs/sdl/external-injects.md), and #1353 published it as semantics only: EI-06 states that no published schema or runnable parser form changes. The compatibility contract (docs/explain/sdl/external-inject-compatibility.md) names the first adoption step: "Closed versioned invocation/outcome carriers and strict bounded serialized ingress, plus direct-core and persistence contextual validation."

No portable carrier exists today for an external trigger request or for a claimed occurrence:

  • raes_backend_protocols/protocols.py::Orchestrator exposes plan start, status, results, history and stop, not a per-inject request.
  • raes/participant_inject_delivery.py::ParticipantInjectOccurrenceAnchor requires event, script and story references, and API-424's ControlInjectEffectModel requires participant, episode and disclosure fields. Both are participant-specific.
  • contracts/schemas/control-plane/ publishes the feat: publish backend operation and supervision contracts #1388 backend operation carriers, whose command is a content-bound artifact reference. No inject contract exists for such a command to name.

#1366 asks for trigger request, occurrence, target/content binding, correlation, authorization context, duplicate handling and execution/readback contracts. This sub-issue covers the trigger request and the claimed occurrence, including target/content binding, authorization context and duplicate handling. The execution/readback contract, participant correlation and backend declaration follow in the PR that closes #1366.

Existing Surface Audit

  • Compiled identities: raes_processor/compiler/addresses.py renders orchestration.inject.<name>, orchestration.inject-binding.<node>.<inject>, orchestration.event.<name>, orchestration.script.<name> and orchestration.story.<name>. raes_contracts.addressing.CompiledAddress validates them.
  • ADR-104 authority: raes_contracts/operation_lifecycle.py::OperationAdmissionContext binds actor, authorization scope, target/run, operation kind, request commitment and parent operation.
  • Retry identity: raes_runtime/control_plane_store.py claims (actor, operation kind, client key) within one target/run store.
  • Bounded types: raes_contracts/contracts/backend_operation.py provides OperationIdentifier, OperationDigest, OperationArtifactReferenceModel and the frozen, closed OperationContractModel.
  • Commitments: raes_contracts.canonical.canonical_json_digest (RFC 8785).
  • Design witness: implementations/python/tests/test_issue_1353_external_inject_design.py models key, occurrence, slot, order and target claims with plain dataclasses. It is not a published contract.

Alternatives

  1. Extend the participant inject carriers with optional fields: rejected. EI-05 and the Define external inject triggering and execution semantics #1353 preflight keep general occurrences independent of participant and control identity, and optional participant fields would not create a general path.
  2. Add an inject-specific OperationKind: rejected for this publication. The Define external inject triggering and execution semantics #1353 preflight requires a new kind to agree with the lifecycle, audit, stored readers and recovery, which is runtime adoption (Execute externally triggered injects through the shared runtime #1367).
  3. Accept an untyped payload or command: rejected by EI-01 and EI-02.
  4. Publish closed draft carriers that reuse the ADR-104 admission context and the feat: publish backend operation and supervision contracts #1388 bounded reference types: selected.

Chosen Architecture

  • inject-trigger-request-v1 (InjectTriggerRequestModel): request key, fresh occurrence ID, target and run scopes, the compiled orchestration plan pin, the canonical inject address and a nonempty set of selected bindings. Each binding names a compiled binding address, a concrete realization instance and its revision, and an instance can be selected once. The request also carries a closed placement (independent, event, or schedule with script, optional story and slot), an optional content-bound input reference with no inline values, and the expected head.
  • inject-occurrence-v1 (InjectOccurrenceModel): the exact request plus the operation ID, the actor-bound OperationAdmissionContext (orchestration kind, same target and run), admission evidence, the expected store revision, the trusted order token (run scope, predecessor equal to the expected head, positive position), scenario, source and realization pins, and required evidence. Request key, occurrence, operation and slot must be distinct values.
  • Duplicate handling: require_inject_trigger_retry returns the original claim only for the same actor, key and request commitment. validate_inject_occurrence_claims rejects a reused retry key, occurrence, operation, schedule slot or order position within one target/run store.
  • Draft schemas under contracts/schemas/control-plane/, publication entries, valid, invalid and context-invalid fixtures (including a participant-free environment trigger), facade exports, an API reference section and a reference page. No runtime route, store, backend call or operation kind changes.

Verification Plan

  • Targeted tests for bounds, placements, distinct identities, retry and claim rules, schema parity and every fixture.
  • tools/check_generated_schemas.py, tools/check_schema_publication.py --base-rev origin/dev, schema coverage and JSON artifact checks.
  • Republish the research-evidence captures and run both evidence checkers.
  • Repository fast feedback against origin/dev.

Activity

  1. doublewhy commented on Oct 13, 2026

    @doublewhy
    ContributorAuthor

    Delivered on dev by #1436 (a391904). Closing by hand because the closing keyword only fires on main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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