Skip to content

Retarget routines via PATCH and enforce target authorization (CL-7353, CL-7354) - #555

Merged
TheGreatAxios merged 5 commits into
cl-7359-myra-routine-toolsfrom
cl-7353-retarget-authz
Sep 2, 2026
Merged

Retarget routines via PATCH and enforce target authorization (CL-7353, CL-7354)#555
TheGreatAxios merged 5 commits into
cl-7359-myra-routine-toolsfrom
cl-7353-retarget-authz

Conversation

@TheGreatAxios

@TheGreatAxios TheGreatAxios commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Implements CL-7353 and CL-7354 on top of CL-7351's target discovery.

CL-7353 — retarget via PATCH

PATCH /routines/:id (both the tenant-session route in routes.ts and
Myra's workflow-run-authenticated route in workflow-routine-routes.ts)
now accepts an optional definitionAssetId, persisted in the same
single updateRoutine UPDATE as every other patchable field — no new
endpoint, no optimistic-locking machinery. The hub's routine launcher
already re-resolves definitionAssetId through
resolveLaunchableDefinition exactly once, at the moment each fire
launches, so a retarget lands atomically for the next run.

CL-7354 — authorize the target

A create, and any PATCH that carries definitionAssetId, now must
clear two gates before persisting: resolveLaunchableDefinition must
resolve (400/404/409 per the existing typed envelope), and the acting
principal must be authorized for workflow-definition:<resolved id> /
read — the same verb listRoutineTargets already checks per row. A
denial is a new typed 403 (routine_target_forbidden). Both routine
route surfaces gained optional grantStore/conditionRegistry deps,
wired in apps/hub/src/index.ts to the same routineGrantStore /
chatConditionRegistry already used elsewhere in this file.

Launch-time (launchAndCorrelate / fireScheduledRoutine) was left
alone: the target is already re-resolved fail-closed at every fire, and
adding a second authorize check there (keyed off the routine creator's
principal for a scheduled fire) would be a real behavior change outside
this ticket's test scope — flagging as a possible follow-up rather than
bundling it in.

Verify

  • bunx tsc --noEmit -p packages/routines -p apps/hub
  • bun test packages/routines/src packages/routines/test (280 pass)
  • bun run scripts/checks/report-error.ts, error-envelope.ts — both ok

Closes CL-7353, CL-7354.

Resolves CL-7353
Resolves CL-7354

@TheGreatAxios
TheGreatAxios changed the base branch from cl-7351-target-discovery to cl-7359-myra-routine-tools September 2, 2026 07:45
A routine's definitionAssetId can now be retargeted through the same
PATCH used for every other field, persisted in one UPDATE alongside
whatever else the patch carries. The launcher already re-resolves
definitionAssetId to the definition that runs at the moment of each
fire, so a retarget lands atomically for the next run without any
optimistic-locking machinery.
A create or PATCH-carried retarget now must clear the same two gates
before it is persisted: resolveLaunchableDefinition must resolve the
asset, and the acting principal must be authorized for
workflow-definition:<id>/read — the same verb listRoutineTargets
already checks per row. A denial is a typed 403 alongside the
existing 400/404/409 target envelopes, on both the tenant-session and
Myra's workflow-run-authenticated routine surfaces.

Also routes a pre-existing catch in postRoutineEnabledNotice through
reportError, since this change's diff now touches that line and
check:report-error requires it.
@TheGreatAxios
TheGreatAxios marked this pull request as ready for review September 2, 2026 11:09
@TheGreatAxios
TheGreatAxios merged commit efc74e7 into main Sep 2, 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