Skip to content

feat(serenity): prompt CRUD proxy with cookie-auth fallback#2397

Draft
rainer-friederich wants to merge 7 commits into
serenityfrom
feat/prompts-management
Draft

feat(serenity): prompt CRUD proxy with cookie-auth fallback#2397
rainer-friederich wants to merge 7 commits into
serenityfrom
feat/prompts-management

Conversation

@rainer-friederich
Copy link
Copy Markdown
Contributor

Stacked on top of #2385 (serenity). Adds prompt-management CRUD proxy and a cookie-auth fallback for upstream Semrush. Diff focuses on the new surface; base reviewers should merge #2385 first.

Summary

  • New REST proxy /v2/orgs/:spaceCatId/brands/:brandId/serenity/prompts* that fans CRUD across Semrush AIO projects via a hardcoded (brandId, category, market, language) → projectId matrix.
  • Matrix lives in src/support/serenity/matrix.js (constant) overridable via SEMRUSH_PROJECT_MATRIX env (JSON).
  • Two auth modes for upstream Semrush:
    1. IMS pass-through (default) — forwards caller's IMS bearer as Auth-Data-Jwt. Requires Adobe ↔ Semrush IMS trust.
    2. Cookie fallback (SEMRUSH_COOKIE) — forwards a logged-in browser session (sso_token) + Chrome UA. Sidesteps the IMS trust assumption. Mirrors the Python tooling in feat-serenity/llmo-data-retrieval-service/scripts/semrush_*.py.
  • Edit = delete+recreate since Semrush exposes no per-prompt PUT. logicalId is a base64url-encoded (brand, category, language, text) descriptor — stable, no DB lookup needed.

Routes (all under organization:read / organization:write)

  • GET /v2/orgs/:spaceCatId/brands/:brandId/serenity/prompts
  • POST /v2/orgs/:spaceCatId/brands/:brandId/serenity/prompts
  • PATCH /v2/orgs/:spaceCatId/brands/:brandId/serenity/prompts/:promptId
  • POST /v2/orgs/:spaceCatId/brands/:brandId/serenity/prompts/bulk-delete

Files

File What
src/support/serenity/rest-transport.js fetch helper, header forwarding (Auth-Data-Jwt or Cookie), typed errors
src/support/serenity/matrix.js hardcoded matrix + lookup helpers
src/support/serenity/handlers/prompts.js list/create/update/bulkDelete business logic
src/controllers/serenity-prompts.js controller, wired into src/index.js
src/routes/index.js route definitions
src/routes/required-capabilities.js per-route capabilities
docs/openapi/serenity-prompts-api.yaml full spec
test/support/serenity/** transport + matrix + handler tests
test/controllers/serenity-prompts.test.js controller tests
test/it/postgres/docker-compose.yml bump mysticat-data-service to v5.14.2
.env.example document SEMRUSH_COOKIE + SEMRUSH_PROJECT_MATRIX

Test plan

  • npx mocha 'test/support/serenity/**/*.test.js' test/controllers/serenity-prompts.test.js test/routes/index.test.js — 140 passing locally on top of serenity branch
  • End-to-end against real Semrush (cookie auth, matrix-driven, returned ~1000 Acrobat US/en prompts)
  • Production deployment with IMS-as-Auth-Data-Jwt — depends on Semrush trust

History

This is the rebased equivalent of the now-closed #2393, applied on top of serenity (#2385). Two cherry-picked commits:

  • feat(serenity): prompt CRUD proxy to Semrush AIO endpoints
  • feat(serenity): cookie auth fallback for Semrush upstream

Related

🤖 Generated with Claude Code

rainer-friederich and others added 2 commits May 12, 2026 14:58
Adds a Semrush-backed prompt CRUD surface that forwards the caller's IMS
bearer token to Semrush as Auth-Data-Jwt. Prompts fan out across Semrush
projects via a hardcoded (brand, category, market, language) -> projectId
matrix; a multi-region prompt lands in one project per region. Edit is
implemented as delete+recreate since Semrush exposes no per-prompt PUT.

Routes (stacked on PR #2387):
- GET    /v2/orgs/:spaceCatId/brands/:brandId/serenity/prompts
- POST   /v2/orgs/:spaceCatId/brands/:brandId/serenity/prompts
- PATCH  /v2/orgs/:spaceCatId/brands/:brandId/serenity/prompts/:promptId
- POST   /v2/orgs/:spaceCatId/brands/:brandId/serenity/prompts/bulk-delete

Matrix is empty by default; populate via SEMRUSH_PROJECT_MATRIX env var
(JSON blob) or by editing src/support/serenity/matrix.js for the hackathon.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a second auth mode for the Serenity proxy. When SEMRUSH_COOKIE is set
in the environment, the transport forwards a shared logged-in browser
session (Cookie + Chrome UA) — Semrush's edge translates the sso_token in
it into the Auth-Data-Jwt the backend wants. This mirrors the Python
tooling in the feat-serenity worktree and sidesteps the Adobe ↔ Semrush
IMS trust assumption that wasn't deliverable in time.

The original IMS pass-through path is unchanged: when SEMRUSH_COOKIE is
empty, the proxy continues to forward the caller's IMS bearer as
Auth-Data-Jwt.

Also bumps the IT Postgres compose to the current mysticat-data-service
image (v5.13.0 -> v5.14.2). Older tags may be retired by ECR retention.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

This PR will trigger a minor release when merged.

rainer-friederich and others added 5 commits May 12, 2026 16:36
…cts endpoint

- Expose `tags: string[]` on each prompt and `availableTags` on the list
  response so the UI can render and pick from real Semrush tags rather than
  collapsing to the first one.
- Accept `topics: string[]` on create/update, fall back to the legacy single
  `topic` shape, and send Semrush the correct text-keyed body for
  `/aio/prompts/tagged` so a prompt can carry multiple tags.
- After every mutation (create/update/bulk-delete) publish the affected
  Semrush projects via `POST /v1/.../publish` so changes leave the project
  draft buffer and show up in subsequent list calls.
- Add `GET /v2/orgs/:org/brands/:brand/serenity/projects` returning the
  brand's matrix projects + derived facets (categories, regions, languages)
  for matrix-driven UI filters and pickers.
- Refresh the matrix example in `.env.example` and add `serenity_setup_readme.md`
  documenting the end-to-end local setup (PRs, services, DB seeds, Semrush
  cookie capture, brandalf + LD overrides, common failure modes).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tatus

- §15 documents the V2 prompts SQL seed that clears the Brand Presence
  "Configuration Required" overlay (BP reads from Postgres while the
  Serenity UI writes to Semrush; they're separate data planes today).
- §16 is a Done / Open status section so the next contributor sees what
  shipped vs what's queued, with the BP-filter-to-Semrush-project plan
  spelled out (3 new filter types, cross-narrowed via matrix facets,
  derived `semrushProjectId` to thread into widget data fetches).
- Also captures the Serenity→Postgres mirror, SR AI Visibility wiring,
  and matrix multi-workspace items.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…loy blocker

PR #2393 was closed and replaced by #2397 against the `serenity` base.
The build is currently failing on the 100% coverage gate (62-97% across
the new serenity files), so no environment has the proxy deployed yet —
locally is the only place to exercise it today.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- New Reporting API transport (Apikey auth) for the v4-raw
  `/external-api/v1/.../products/ai/elements/{elementId}` endpoint
  that backs the BP KPI cards.
- `GET .../serenity/workspaces/:workspaceId/projects` — active AIO
  projects in a workspace, used by the BP Category filter.
- `GET .../serenity/projects/:workspaceId/:projectId/models` — the
  project's configured AI models, used by the BP Platform filter.
- `GET .../serenity/projects/:workspaceId/:projectId/tags` — the
  project's tags, used by the BP Tags filter.
- `POST .../serenity/reporting/elements/:elementId` — passthrough to
  the Reporting API for KPI card / trend chart queries.
- Updated serenity setup readme with the new endpoints,
  `SEMRUSH_REPORTING_API_KEY` env var, and BP flow walk-through.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
§4 now points at §10.3 for the no-Postgres flow. §10.3 adds the full
STUB_DATA_SERVICE walkthrough — fixture URL pattern table, trade-offs,
and the webpack-restart caveat. §13 + §16 list the new
`dataServiceStub.ts` file and the `friendlyCategoryLabel` per-project
Category labels (General / Doodle / GMI / HEIC to PDF / Adobe Stock).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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