feat(drs-client): generic createSchedule with fixed cadences + tenant-isolation guards#1816
Open
dzehnder wants to merge 2 commits into
Open
feat(drs-client): generic createSchedule with fixed cadences + tenant-isolation guards#1816dzehnder wants to merge 2 commits into
dzehnder wants to merge 2 commits into
Conversation
…tenant-isolation guards
Add DrsClient#createSchedule, a generic recurring-schedule creator for the LLMO
prompt-suggestion pipelines (semrush / agentic-traffic / synthetic-personas),
alongside the existing createExperimentSchedule.
- Extract a shared private #buildScheduleBody so createExperimentSchedule and
createSchedule build the POST /schedules envelope through one path and cannot
drift.
- Constrain input: frequency is always 'cron' and the cron is DERIVED from a small
cadence enum (SCHEDULE_CADENCES: twice_monthly -> `0 {H} 1,15 * *` with a
deterministic per-site hour jitter; quarterly -> `0 8 1 1,4,7,10 *`). Arbitrary
caller-supplied cron is intentionally not accepted (leaked-key Fargate-storm guard).
- Security hardening (defense in depth; DRS also enforces server-side): reject any
caller-supplied imsOrgId (ims_org_id / imsorgid, any case, any nesting depth) inside
job_config; cap description (1024 chars) and serialized job_config (100 KB); the
api key remains header-only and is never a loggable argument.
- Idempotent: treat a 409 dedup as success, returning { scheduleId, alreadyExisted }.
Additive only — no breaking change. spacecat-api-service will consume createSchedule
for onboarding triggers in a downstream PR.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
This PR will trigger a minor release when merged. |
Stop computing cron client-side for createSchedule. DRS derives frequency +
cron server-side from job_config.cadence for prompt-suggestion providers and
overwrites anything sent, so the client's jitter (Math.imul) differed from
DRS's sha256 % 24 and logged a fire time that never happened. The client now
sends only the cadence label; #buildScheduleBody sends frequency/cron_expression
only when a caller-supplied cron is authoritative (the experiment path).
Fix the dedup signal: DRS returns HTTP 200 { idempotent: true, schedule_id }
on a deterministic-id collision (not 409 + existing_schedule_id), and the
create is create-only. Surface that as alreadyExisted: true and document that a
changed cadence/job_config is not applied on a repeat call.
Also: use Buffer.byteLength for the job_config byte cap, extend the imsOrgId
key regex to hyphen variants, add a recursion depth guard to assertNoImsOrgId,
and validate priority against { HIGH, LOW }.
Delete cronForCadence/siteHourJitter and their now-dead cron logging.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a generic
DrsClient#createSchedule(...)to@adobe/spacecat-shared-drs-clientfor creating recurring DRS schedules on a fixed cadence — the mechanism the LLMO "prompt suggestion" pipelines (prompt_generation_semrush,prompt_generation_agentic_traffic,prompt_generation_synthetic_personas) need to run on a recurring basis and at onboarding. Sibling to the existingcreateExperimentSchedule; both now build thePOST /schedulesenvelope through one shared private#buildScheduleBody, so the two paths cannot drift.This is Phase 2 of the DRS prompt-suggestion schedules + onboarding-triggers effort.
spacecat-api-serviceconsumescreateSchedulein a downstream PR (onboarding triggers);spacecat-audit-workeralso depends on this client, and the change is purely additive so it is unaffected.New API
New export:
SCHEDULE_CADENCES = { TWICE_MONTHLY: 'twice_monthly', QUARTERLY: 'quarterly' }.Design decisions
frequencyis always'cron'; the cron is derived from the cadence enum — a raw cron string is never accepted.twice_monthly->0 {H} 1,15 * *whereHis a deterministic per-site hour (thundering-herd guard);quarterly->0 8 1 1,4,7,10 *. This closes the "leakedx-api-keysets* * * * *" fleet-wide Fargate-storm risk.imsOrgId(alsoims_org_id/imsorgid, any case, at any nesting depth) insidejob_configis rejected. DRS derives the isolation key fromsite_idserver-side; the client never accepts an org id. The guard is in the shared body-builder, socreateExperimentSchedulegets it too.descriptioncapped at 1024 chars and the serializedjob_configat 100 KB (DynamoDB oversized-item guard).409dedup from DRS is treated as success (alreadyExisted: true), matchingcreateBrandPresenceSchedule.Tests
npm run lintandnpm testfor the package both pass locally: 133 passing, 100% statements / branches / functions / lines (package enforces 100% branch coverage). New coverage includes cadence-derived cron, per-site jitter determinism, 409 dedup, imsOrgId rejection (nested + in arrays), size caps, and error paths.Versioning
Additive
feat:— semantic-release will publish 1.14.0 (current 1.13.0). No breaking change.🤖 Generated with Claude Code