Skip to content

docs(adr): accept ADR-0001 — shared Semrush client ownership boundary - #1781

Merged
aliciadriani merged 10 commits into
mainfrom
docs/adr-0001-semrush-client-ownership
Jul 16, 2026
Merged

docs(adr): accept ADR-0001 — shared Semrush client ownership boundary#1781
aliciadriani merged 10 commits into
mainfrom
docs/adr-0001-semrush-client-ownership

Conversation

@aliciadriani

@aliciadriani aliciadriani commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Spec

LLMO-5975: agree the ownership boundary for the shared Semrush client before the facade
build-out (LLMO-5977) lands, so subsequent PRs don't re-litigate it.

Boundary decided:

  • Shared client owns transport: IMS Bearer auth, retries/backoff, request timeouts, a
    typed error taxonomy.
  • Consumers own: error→HTTP translation, caching, redaction.
  • Test: is it true for every consumer (→ shared) or specific to one (→ consumer)?

LLMO-5980 disposition: investigation confirmed transport behavior has already
diverged between spacecat-shared's client and spacecat-api-service's hand-built
Serenity transport (shared has retry/backoff, api-service has none). That divergence
is closed directly via a targeted retry-parity fix in api-service (tracked separately,
not gated on this ADR). Migrating api-service onto the shared client itself is recorded
as "revisit deliberately" — not funded now, not closed as a non-goal. It's a deliberate
future call, sequenced after the facade exists, not something the resilience gap should
stampede.

Implementation plan

  • Adds docs/adr/0001-shared-semrush-client-ownership.md — status Accepted, starts a
    docs/adr/ practice in this repo (previously no ADR file/directory existed anywhere
    in spacecat-shared; tickets were tracked purely via inline external Jira links).
  • No code changes. Doc-only PR.
  • Follow-on work referenced in the ADR: LLMO-5977 (facade, gated on this), LLMO-5978+5979
    (typed errors + timeouts, one combined hardening PR), LLMO-5980 (deferred), LLMO-5976
    (spec-verify CI gate — independent, already shipped in test(project-engine-client,user-manager-client): spec-verify checksum gate (LLMO-5976) #1777).

Alicia Adriani added 2 commits July 6, 2026 12:58
Records the accepted boundary for LLMO-5975: shared client owns transport
(auth, retry/backoff, timeouts, typed errors); consumers own error->HTTP
translation, caching, redaction. Records LLMO-5980 (api-service migration)
as deliberately deferred, not auto-funded by the confirmed transport-drift
trigger -- the live resilience gap is closed directly in api-service
instead (tracked separately).
Full revision, not a patch: adds Scope + Non-goals sections, rewrites Context
to reflect that api-service already consumes the shared Project Engine/User
Manager clients (retry was disabled via maxRetries:0, restored by #2766),
and replaces the LLMO-5980 duplication framing with the confirmed four-path
coverage map (Project Engine + User Manager migrated; Elements and AI
Visibility are not). Boundary section unchanged.
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

This PR will trigger no release when merged.

@aliciadriani aliciadriani left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review(ADR-0001: shared Semrush client ownership)

Summary. Clear, well-scoped decision record: shared client owns transport (auth / retry / timeouts / typed errors); consumers own error→HTTP translation, caching, redaction — with an explicit boundary test and honest non-goals. Verified against code: api-service already consumes the shared clients; elements-transport.js is a hand-rolled POST on SEMRUSH_PROJECTS_BASE_URL with a 504 timeout and no retry (matches the Elements claim); LLMO-5976 shipped in #1777. One factual staleness to fix.

Must Fix

None.

Should Fix

  • #2766 is still OPEN (verified today) — the ADR presents retry as already restored/closed. Lines 17 / 40 / 41 / 60 read as done. Until #2766 merges, the migrated surfaces still run one-shot in prod. Applying a minimal pending-merge correction — factual only; the boundary decision is unchanged.

Nits

  • Follow-on drift: line 74 says LLMO-5978 + 5979 land "together as one hardening PR", but 5979 shipped standalone in #1819. Left as a comment for you to reframe — it's your plan narrative, not a fact I'll rewrite.

What's Good

  • The "is it true for every consumer, or specific to one?" test is a crisp, reusable boundary heuristic.
  • Redefines LLMO-5980 accurately to the two real remaining surfaces — matches the code (elements-transport.js, grpc-transport.js).
  • Non-goals explicitly park AI Visibility (gRPC/OAuth2) rather than over-reaching.


The Semrush Project Engine and User Manager clients exist as typed wrappers in `spacecat-shared` (`@adobe/spacecat-shared-project-engine-client`, `@adobe/spacecat-shared-user-manager-client`; PR #1661 lineage: IMS Bearer auth, retry/backoff).

`spacecat-api-service` **already consumes these shared clients** for its Project Engine and User Manager call paths (`controllers/serenity.js`, `controllers/brands.js`, `support/serenity/**`) — a migration that landed in prior shipped work. That migration pinned `maxRetries: 0` to preserve the previous one-shot behaviour, which silently disabled the shared clients' retry in production. PR #2766 removes that pin, restoring retry/backoff on those paths.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified today: PR #2766 is still OPEN (not merged). So "removes that pin, restoring retry/backoff" isn't true yet — the migrated surfaces still run one-shot in prod until it merges. Softening to a pending-merge framing (factual correction; the boundary decision is untouched).

Comment thread docs/adr/0001-shared-semrush-client-ownership.md
Comment thread docs/adr/0001-shared-semrush-client-ownership.md

**LLMO-5980 is redefined as: close the two remaining surfaces, on their own merits.**

- **Elements** — same paradigm as Project Engine (REST, IMS Bearer, *same gateway* `SEMRUSH_PROJECTS_BASE_URL`), one endpoint (`fetchElement`, POST), hand-rolled, zero retry. This is the same resilience gap #2766 just closed, on the same gateway. It should be closed as a small, scoped follow-up — either by consuming the shared client if the endpoint fits it, or by mirroring the retry behaviour in place. Tracked separately; not bundled with the boundary decision.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified against spacecat-api-service/src/support/elements/elements-transport.js: POST, reads SEMRUSH_PROJECTS_BASE_URL, 504-on-timeout, no retry loop — so "hand-rolled, zero retry, same gateway" is accurate. (The path prefix is /enterprise/pages/api/v3, not projects/api, but the gateway/env is the same as stated.)


- **AI Visibility transport (gRPC/HTTP2 + OAuth2).** Different protocol, different auth model; it does not drop onto the REST/IMS-Bearer shared client. Whether the shared-client boundary should ever stretch to cover gRPC/OAuth2 — or whether that surface gets its own client — is a separate decision, to be made when someone actually works that surface, not pre-emptively here.

## Consequences

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Factual: this says the gap "is closed (#2766)", but #2766 is still open. Changing to "will be closed once #2766 merges".

- Consumers each implement error→HTTP translation. Mitigated by the typed error taxonomy being clear enough that translation is mechanical.

## Follow-on work

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit / plan drift: 5979 actually shipped on its own in #1819 (per your direction), not bundled with 5978. Flagging rather than rewriting — your call how to reframe the follow-on plan.


- **LLMO-5977** — client facade in `spacecat-shared` (makes the boundary real in code). Gated on this ADR.
- **LLMO-5978 + LLMO-5979** — typed errors + request timeouts, landing together as one hardening PR.
- **LLMO-5980** — close Elements (small, same-shape); AI Visibility deferred as a non-goal.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified: LLMO-5976 spec-verify gate is Closed and shipped in PR #1777. Accurate.

ADR-0001 stated the api-service retry gap was already restored/closed by
#2766, but #2766 is still open. Correct to pending-merge framing across the
Context, the consumption table, and the Consequences. Factual only — the
ownership boundary decision is unchanged.

LLMO-5975

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@aliciadriani
aliciadriani requested a review from MysticatBot July 15, 2026 23:03

@MysticatBot MysticatBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @aliciadriani,

Verdict: Approve - clean boundary ADR; minor factual drift in the follow-on section, non-blocking.
Complexity: LOW - small docs-only change, single file.
Changes: Establishes ADR-0001 defining the shared Semrush client ownership boundary - transport in shared client, context in consumers (1 file).
Note: Recommend a human read before merge - this change creates an architectural decision record (docs/adr/). The bot review is a complement to, not a replacement for, a human read here.

Non-blocking (3): minor issues and suggestions
  • nit: Follow-on line says LLMO-5978 + 5979 land "together as one hardening PR" but they are tracked separately (5979 is PR spacecat-shared#1819, currently open) - docs/adr/0001-shared-semrush-client-ownership.md:74
  • suggestion: PR 2766 is in spacecat-api-service, not this repo; disambiguate with a repo qualifier (e.g. spacecat-api-service#2766) or full URL to avoid reader confusion - docs/adr/0001-shared-semrush-client-ownership.md:7
  • suggestion: Add a one-line rationale for why caching stays consumer-side (e.g. "staleness tolerance varies per consumer") to make the boundary more defensible against future re-litigation - docs/adr/0001-shared-semrush-client-ownership.md:34

Skill: pr-review | Model: us.anthropic.claude-opus-4-6-v1[1m] | Duration: 7m 44s | Cost: $2.50 | Commit: 5c2e242ad94ab295e5427f72e80ed9d857a266ee
If this code review was useful, please react with 👍. Otherwise, react with 👎.

@MysticatBot MysticatBot added ai-reviewed Reviewed by AI complexity:low AI-assessed PR complexity: LOW needs-human-review labels Jul 15, 2026
…tionale, follow-on drift

- Qualify cross-repo references to spacecat-api-service#2766 (it's not in this repo).
- Add a one-line rationale for why caching stays consumer-side (scope/keying/
  staleness vary per consumer) so the boundary is defensible against re-litigation.
- Correct the follow-on plan: 5979 shipped separately in #1819, not bundled with
  5978 as "one hardening PR".

LLMO-5975

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@aliciadriani aliciadriani left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed MysticatBot review (commit 54da758)

  • suggestion — qualify cross-repo #2766. Now spacecat-api-service#2766 everywhere it appears (Relates-to, Context, table, Consequences) — it's not in this repo.
  • suggestion — caching rationale. Added why caching stays consumer-side (scope / keying / staleness tolerance vary per consumer, e.g. api-service's workspace-layer cache) so the boundary resists re-litigation.
  • nit — follow-on drift. Corrected: 5979 shipped on its own in #1819, not bundled with 5978 as "one hardening PR". (This matches the same item in my own review.)

Also noting MysticatBot's meta-point: this is an ADR, so a human read before merge is warranted — the bot + this automated review complement, not replace, that.

Comment thread docs/adr/0001-shared-semrush-client-ownership.md
Comment thread docs/adr/0001-shared-semrush-client-ownership.md
## Follow-on work

- **LLMO-5977** — client facade in `spacecat-shared` (makes the boundary real in code). Gated on this ADR.
- **LLMO-5979** — request timeouts. Shipped on its own in #1819 (open), not bundled with 5978.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied — the follow-on now reflects reality: 5979 shipped separately in #1819; 5978 is the remaining hardening item, gated on the facade (5977).

@aliciadriani
aliciadriani requested a review from MysticatBot July 15, 2026 23:18

@MysticatBot MysticatBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @aliciadriani,

Verdict: Approve - all prior nits addressed; one minor factual inconsistency remains, non-blocking.
Complexity: LOW - small docs-only change, single file.
Changes: Adds ADR-0001 defining the shared Semrush client ownership boundary (transport in shared client, context in consumers) with addressed follow-on nits (1 file).
Note: Recommend a human read before merge - this change creates an architectural decision record (docs/adr/). The bot review is a complement to, not a replacement for, a human read here.

Non-blocking (1): minor issues and suggestions
  • nit: "Shipped on its own in #1819 (open)" is contradictory - a PR that is open has not shipped. Use "In progress in #1819 (open)" or, if merged, drop "(open)" - docs/adr/0001-shared-semrush-client-ownership.md:73

Previously flagged, now resolved

  • Cross-repo PR ref now qualified as spacecat-api-service#2766
  • Caching rationale added (scope/keying/staleness vary per consumer)
  • Follow-on items (LLMO-5978, 5979) now described with correct independent tracking

Skill: pr-review | Model: us.anthropic.claude-opus-4-6-v1[1m] | Duration: 9m 10s | Cost: $2.24 | Commit: 54da758bc959a72252da167c5823681ac3e20d73
If this code review was useful, please react with 👍. Otherwise, react with 👎.

MysticatBot nit: an open PR hasn't shipped. Reword to "In progress in #1819
(open)".

LLMO-5975

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@aliciadriani aliciadriani left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed MysticatBot re-review (commit incoming)

  • nit — "Shipped … (open)" contradiction. Reworded to "In progress in #1819 (open), on its own PR rather than bundled with 5978." An open PR hasn't shipped — good catch.

All prior items resolved; no other findings.

## Follow-on work

- **LLMO-5977** — client facade in `spacecat-shared` (makes the boundary real in code). Gated on this ADR.
- **LLMO-5979** — request timeouts. Shipped on its own in #1819 (open), not bundled with 5978.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the contradiction — "In progress in #1819 (open)" instead of "Shipped … (open)".

@aliciadriani
aliciadriani requested a review from MysticatBot July 15, 2026 23:30

@MysticatBot MysticatBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @aliciadriani,

Verdict: Approve - all prior nits addressed; no new issues.
Complexity: LOW - small docs-only change, single file.
Changes: Establishes ADR-0001 defining the shared Semrush client ownership boundary - transport in shared client, context in consumers (1 file).
Note: Recommend a human read before merge - this change creates an architectural decision record (docs/adr/). The bot review is a complement to, not a replacement for, a human read here.

Previously flagged, now resolved

  • "Shipped on its own in #1819 (open)" contradiction corrected to "In progress in #1819 (open)" - consistent with the PR's open status

Skill: pr-review | Model: us.anthropic.claude-opus-4-6-v1[1m] | Duration: 7m 50s | Cost: $2.27 | Commit: 34a6ed979ee5d63d6e17e93f5c170678328c08e0
If this code review was useful, please react with 👍. Otherwise, react with 👎.

Alicia Adriani and others added 2 commits July 16, 2026 01:43
Two follow-on lines drifted since the ADR's 2026-07-06 date:
- LLMO-5976 (spec-verify gate) shipped via #1811, not #1777 (#1777 is still open).
- LLMO-5979 (request timeouts) has since shipped in #1819 (was "in progress / open").

Docs-only; no decision change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@aliciadriani
aliciadriani requested a review from MysticatBot July 16, 2026 00:40

@MysticatBot MysticatBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @aliciadriani,

Verdict: Approve - all prior nits addressed; latest commit corrects stale follow-on PR refs, no new issues.
Complexity: LOW - small docs-only change, single file.
Changes: Corrects stale follow-on PR references in ADR-0001 to reflect current tracking state (1 file).
Note: Recommend a human read before merge - this change creates an architectural decision record (docs/adr/). The bot review is a complement to, not a replacement for, a human read here.

Previously flagged, now resolved

  • Follow-on PR references now accurately reflect current tracking (LLMO-5979 in progress in its own PR, LLMO-5976 shipped in PR 1811)

Skill: pr-review | Model: us.anthropic.claude-opus-4-6-v1[1m] | Duration: 1m 2s | Cost: $2.46 | Commit: 597a47c0b48b164992749f0cabd588b2e39ec51a
If this code review was useful, please react with 👍. Otherwise, react with 👎.

@aliciadriani aliciadriani self-assigned this Jul 16, 2026
@aliciadriani
aliciadriani enabled auto-merge (squash) July 16, 2026 03:06
@aliciadriani
aliciadriani merged commit 9f7293c into main Jul 16, 2026
5 checks passed
@aliciadriani
aliciadriani deleted the docs/adr-0001-semrush-client-ownership branch July 16, 2026 03:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-reviewed Reviewed by AI complexity:low AI-assessed PR complexity: LOW needs-human-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants