Skip to content

serenity: allow generic tags (arbitrary <dimension>:<value>, incl. type:) on POST /serenity/tags #2731

Description

@rainer-friederich

Summary

Allow POST /v2/orgs/:org/brands/:brand/serenity/tags to create generic tags — arbitrary <dimension>:<value> tags — instead of only the category / topic open dimensions. In particular, support creating tags under the type: dimension (and other prefixes), which the endpoint currently rejects.

Current behavior

createTag (added in #2730) is deliberately narrow:

  • src/support/serenity/prompt-tags.jsCREATABLE_TAG_DIMENSIONS = [CATEGORY, TOPIC]. The other dimensions in TAG_DIMENSION (source, intent, type) are closed taxonomies with fixed enums (SOURCE_TAG / INTENT_TAG / TYPE_TAG) and are not freely creatable.
  • src/support/serenity/handlers/tags.jsparseCreateTagBody:
    • type must be in CREATABLE_TAG_DIMENSIONS → a type: (or any non-category/topic) value is a 400.
    • name must not contain : → you can't pass a fully-qualified type:branded as the name either (it would otherwise double-prefix to category:type:branded).
  • The stored tag is tagFor(type, name) = "<type>:<name>".

So today there is no way to register e.g. type:<something> or any generic <prefix>:<value> tag through this endpoint.

Requested change

Support generic tags on the same endpoint. Two design options (pick one — needs a decision):

  1. Widen the dimension allow-list. Add type (and optionally source / intent) to CREATABLE_TAG_DIMENSIONS, keeping the type + name (no-colon) composition. Simple, but it conflates "open" and "closed" taxonomies — the closed ones have fixed enums for a reason (classification semantics, the onboarding INTENT_MAP, etc.), so freely creating arbitrary type:foo values may be undesirable.
  2. Add an explicit generic/raw mode. Allow the caller to pass a full tag string (e.g. name: "type:branded" with a generic/raw type, or a dedicated field), relaxing the no-colon rule for that mode and storing the name verbatim. Keeps category/topic strict while making genericness opt-in and unambiguous.

Either way, update:

  • parseCreateTagBody validation (and the name must not contain ":" rule),
  • CREATABLE_TAG_DIMENSIONS / the SerenityCreatableTagType mirror in elmo (project-elmo-ui src/types/serenity.ts),
  • docs/openapi/serenity-api.yaml (the type enum / request schema),
  • unit + IT tests.

Mock support (spacecat-shared project-engine-client)

Likely no mock change needed — the mock already stores arbitrary tag names verbatim:

Caveats to verify if option 2 (colons in names) is chosen:

  • Confirm Counterfact request validation against the overlayed OpenAPI doesn't constrain the names string format.
  • Confirm tagId collision behavior and GET /aio/tags search filtering still behave for prefix:value names.

Out-of-scope but must be checked first: real Semrush contract

The mock is permissive, but the gating question is whether the live Semrush AIO gateway accepts arbitrary <prefix>:<value> tag names — especially under the reserved type: / source: / intent: dimensions, which may have upstream semantics. Validate against live before widening, so the mock and prod don't diverge.

Context

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions