Skip to content

feat(conductor): principalRef identity-bridge for channel-binding delivery (P2a)#389

Merged
Weegy merged 1 commit into
mainfrom
feat/conductor-binding-principalref
Jun 30, 2026
Merged

feat(conductor): principalRef identity-bridge for channel-binding delivery (P2a)#389
Weegy merged 1 commit into
mainfrom
feat/conductor-binding-principalref

Conversation

@Weegy

@Weegy Weegy commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Conductor identity-bridge: principalRef for reminder/approval delivery (P2a)

The Conductor delivers proactive reminders/approvals by looking up a channel binding keyed by the human-step principal / role-holder id. But the binding is keyed by the channel-native id (for Teams, the AAD object id) while operators address people by email (role holders are entered as holder@email). So delivery silently misses and the await is flagged unreachable.

This is the OSS half of the fix. It threads an operator-addressable principalRef through the routines turn-capture seam so a channel plugin can supply the email, and keys the binding by it.

Changes

  • @omadia/plugin-api — add optional principalRef?: string to captureRoutineTurn's info. Purely additive; the only OSS caller is routines/integration.ts, so no compiled plugin breaks.
  • routines/integration.ts — forward principalRef through the onTurnCaptured observer.
  • index.ts — key the binding upsert via bindingKeyForTurn(info) = principalRef || userId (||, so a blank principalRef falls back instead of writing an empty, never-matched key).
  • conductor/principalId.ts (new) — canonicalizePrincipalId (trim + lowercase) + bindingKeyForTurn.
  • conductor/channelBindingStore.ts — canonicalize the key on both write (upsert) and read (get/getMany), so casing/whitespace differences between the channel-supplied key and an operator-typed holder id can never cause a silent unreachable. getMany returns the result keyed by the caller's original holder id.

Staging

Inert until a channel actually sets principalRef — the Microsoft Teams plugin half (resolve + pass the user's email) follows in a private-repo change once this merges, mirroring how the channel event-emit plugin work staged behind #388.

Review & tests

Double-reviewed (independent correctness/cleanup pass + an adversarial Codex pass, APPROVE-WITH-CHANGES). Folded: the normalization mismatch (the make-or-break for delivery), the empty-string ??|| gap, a stale identity-contract comment, and test import + keying coverage. Build + lint clean; 54 conductor/routines tests pass incl. new coverage for the forwarding, the canonicalization (case-insensitive match), and bindingKeyForTurn.

…ivery (P2a)

Conductor reminders/approvals are delivered by looking up a channel binding keyed
by the human-step principal / role-holder id, but the binding was keyed by the
channel-native id (Teams AAD object id) while operators address people by email,
so delivery silently missed. This threads an operator-addressable `principalRef`
through the routines turn-capture seam and keys the binding by it.

- plugin-api: add optional `principalRef?` to captureRoutineTurn's info (additive
  contract; the only OSS caller is integration.ts, so no compiled plugin breaks).
- routines/integration.ts: forward principalRef through onTurnCaptured.
- index.ts: key the binding upsert via bindingKeyForTurn (principalRef || userId --
  `||` so a blank principalRef falls back instead of writing an empty key).
- principalId.ts: canonicalizePrincipalId (trim + lowercase) + bindingKeyForTurn.
- channelBindingStore: canonicalize the key on BOTH write (upsert) and read
  (get/getMany) so casing/whitespace between the channel-supplied key and an
  operator-typed holder id can never cause a silent `unreachable`; getMany returns
  results keyed by the caller's original holder id.

Inert until a channel sets principalRef (the Teams plugin half, P2b, follows once
this merges). Reviewed (Claude + Forge APPROVE-WITH-CHANGES): folded the
normalization mismatch (the make-or-break), the empty-string ??->|| gap, the stale
identity-contract comment, and the test import + keying coverage. Build + lint + 54
conductor/routines tests green.
@Weegy Weegy merged commit 164d6ac into main Jun 30, 2026
7 checks passed
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