feat(tags): automate Semaphore taxonomy sync (#2184) - #2197
Merged
Conversation
Replaces the manual, one-off Semaphore batch load with a weekly, DB-flag-gated cron that pulls the SAPCore model from the Semaphore SES allterms REST API and upserts Tags keyed on semaphoreId. Pipeline (all pure/injectable for test): client.fetchAllTerms -> mapper.mapAllTerms -> applier.applyTerms - srv/lib/semaphore-sync/client.js SES REST client; resolves semaphore-destination, fails shut on any HTTP/parse/shape error. - srv/lib/semaphore-sync/mapper.js pure SES term -> tag row; titlePath + normalized name; config-driven class->flag mapping. - srv/lib/semaphore-sync/applier.js upsert keyed on semaphoreId (distinct from the CSV importer's name-keyed path); adopts legacy name matches; idempotent; dryRun. - srv/jobs/semaphore-tag-sync-job.js orchestrator; flag-gated, config-driven, fail-shut. Registered Sunday 04:47 UTC. - SEMAPHORE_SYNC_ENABLED DB feature flag (default OFF, dev-only); ImsConfig semaphore.sync.* tuning keys (dryRun defaults ON). - cds.requires.semaphore REST destination + .cdsrc.json mock for dev/unit. No schema change: Tags already carries semaphoreId/isActualTag/isInterestItem. Ships dark; validate on DEV in dryRun before enabling. 37 new unit tests. Design: docs/superpowers/specs/2026-09-08-2184-semaphore-auto-sync-design.md
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.
Closes #2184 (automation) — ships dark behind a default-OFF DB flag; awaits the Semaphore Service Account +
semaphore-destinationbefore it can be enabled. Service Account requested by email in parallel (draft in the issue comment).What
Replaces the manual one-off Semaphore batch load with a weekly, flag-gated cron that pulls the SAPCore model from the Semaphore SES
alltermsREST API and upsertsTagskeyed onsemaphoreId(a renamed term updates in place instead of duplicating).srv/lib/semaphore-sync/client.jssemaphore-destination; fails shut on any HTTP/parse/shape errorsrv/lib/semaphore-sync/mapper.jstitlePath+ normalizedname; config-driven class→flag mappingsrv/lib/semaphore-sync/applier.jssemaphoreId(distinct from the CSV importer); adopts legacy name matches; idempotent;dryRunsrv/jobs/semaphore-tag-sync-job.jsConfig (all DB-driven, no env vars)
SEMAPHORE_SYNC_ENABLED— DB feature flag (ImsConfigflag.semaphore.sync), default OFF,dev-only. Off → no-op.ImsConfig semaphore.sync.{model,lang,filter,actualTagClasses,interestItemClasses,dryRun}tune a run without redeploy.dryRundefaults ON — first enabled runs only report the plan.cds.requires.semaphoreREST destination (semaphore-destination);.cdsrc.jsonmock for dev/unit. Token lives in the destination / Credential Store — never in source.Safety
Tagsalready carriessemaphoreId/isActualTag/isInterestItem(Tutorial and Tag API enhancements to eliminate SAGE sqlite caching dependencies #385 PR-1).dryRunbefore flippingdryRunoff, then enable on PROD.Open items (need the Service Account)
Confirm the live
pathsshape + the class URIs for actual-tag vs interest-item, and the destination auth flavour, then tune the class lists indryRunon DEV. Mapper is deliberately conservative until then (every term an actual tag, none an interest item).Tests
37 new unit tests (mapper / client / applier / job), all green.
npx cds compile srvclean. CSV tag-import path untouched (existing applier tests still pass).Design:
docs/superpowers/specs/2026-09-08-2184-semaphore-auto-sync-design.md