Skip to main content

RFC Review: Centralized Web Session — CRM Frontend Integration of @mekari/sdk Session

Executive Summary

  • Overall Score: 6.5/10
  • Rating: Needs Work
  • RFC Type: frontend
  • Sub-Type: enhancement
  • Assessment Confidence: High
  • Applied Caps/Gates: CNT = 5.5 (below 7.0 → no soft cap triggered; CNT < 5.0 cap NOT applied). No hard cap fired; overall held to 6.5 by judgment — 4 critical blockers prevent end-to-end agentic build.
  • Implementation Readiness Verdict: HOLD — resolve Q1–Q4 (critical) before full agent execution; chunks 2, 3, 6 are independently executable now
  • Report Path: /Users/mekari/Documents/crm/rfc-review-report.md
  • RFC Author: Qontak CRM Frontend | Reviewed: 2026-06-28

This RFC is among the most disciplined integration specs reviewable: it carries a full Repo Reading Guide (§2.0), a Source Verification table that distinguishes verified anchors from UNVERIFIED unknowns, seven ADR blocks, a per-story change map, and a numbered rollback recipe. An AI agent could execute chunks 2, 3, and 6 (msli helper, plugin scaffold + toggle gate, observability) today without asking a question. It cannot complete the integration's core purpose — constructing new Session({ current_user: user_sso_id }) — because the source of user_sso_id in CRM's /users/me response is explicitly UNVERIFIED (§2.0 Source Verification, Q2). The biggest strength is anti-hallucination honesty: every unknown is flagged rather than invented. The biggest gap is that three of the seven decisions (D5 switch_user, D7 current_company, plus the D1 dependency availability) terminate in critical open questions, so the RFC author correctly self-marks "Ready for agent execution: no" (§7). The one thing that must change before agentic execution: confirm user_sso_id's field path in /users/me (Q2) — without it the SDK input is a guess and every event handler compares against an unknown.


Quick Verdict

Why this RFC can be implemented agentically:

  • Scope, file list, plugin registration point (nuxt.config.js:58), and reuse targets (store/user.js:userLogout) are pinned to verified line numbers.
  • Failure paths (server_down fallback, fail-closed toggle read, switch_user interim) are drawn as sequence + state diagrams with explicit branches.
  • Each execution chunk (§4.C) has an assertable acceptance criterion tied to a real package.json script.

Why this RFC will cause agent guessing or rework:

  • The SDK constructor input user_sso_id has no verified source — agent would guess a field on $auth.user (CNT, Q2).
  • switch_user resolves only to an "interim sign-out" because the real SSO-autologin contract is unknown for CRM's token model (TDC, Q1).
  • Exact centralized_session code string and @mekari/sdk registry path are placeholders (DEP, Q3/Q6).

PRD → RFC Traceability Matrix

PRD exists (Confluence driver RFC, linked §1.5). Standard format applies.

PRD ElementRFC SectionCoverage
Overview / known stale-session issues§1.1Full — CRM-relevant cases mapped (logout, switch account)
Success Criteria§1.2Partial — FE-slice subset; SDK/Redis criteria correctly excluded as A&L-owned
Out of Scope§1.3Full — inherited + CRM additions
Dependencies (SDK, SM, Redis)§2.0 / §5Partial — SDK consumed; SM+Redis flagged as A&L deps (Q6 registry open)
How to use the SDK§2.4 / §2.2Full — mapped to plugin + session.on()
Local Storage (msli)§2.2 / §2.3Full — new helper, 2h window
Cookies (_mekari_account)§2.0 / §2.3Full — read-only contract documented
SDK event contract (4 events)§2.4 InboundFull — all four handled with payload + CRM action
FE Web Session Flow§2.5 / §5 Q1Missing — CRM is token-based, mapping unresolved (Q1 critical)
OAuth2 Authz-Code Flow§5 Q1Missing — CRM does not use authz-code; explicitly unresolved
User Switch Account§2.6 / §5 Q1Partial — interim sign-out only; seamless switch deferred (ADR-5)
current_company sync§2 ADR-7 / §5 Q4Missing — deferred, no CRM endpoint exists (Q4 critical)
Database Model (no changes)§2.3Full — confirmed no DDL
HA & Security§3Partial — FE CSP/origin; backend p95/RPS A&L-owned
Rollout Plan§4Full — CRM = step 5 post-Launchpad

Summary: ~11 of 17 mapped PRD elements fully covered, 3 partial, 3 missing (all 3 missing are the critical-tagged token-model/switch/current_company items). No RFC decision lacks PRD justification — no scope creep detected.


Scorecard

Frontend Scorecard (11 categories)

CategoryScoreEvidence-Based Rationale
PRT — PRD Traceability7.5Detail 1.A gives a full bidirectional PRD-section coverage matrix; reverse mapping clean (no unjustified additions). Docked for 3 missing mappings (Web Session Flow, OAuth2 flow, current_company) that are the integration's hard parts.
TDC — Technical Decisions6.07 ADRs with options + rationale + reversibility (strong). But D5 (switch_user) is "interim" pending Q1, D7 (current_company) deferred pending Q4 — two decisions resolved only as "defer/interim," not closed. Agent cannot build the seamless paths.
CNT — Contract Specificity5.5SDK event payloads tabulated (§2.4 Inbound); msli/cookie artifacts shaped (§2.3); data-fetching/refresh strategy stated (throttled session.refresh() + router afterEach, ADR-3). But the constructor input user_sso_id source is UNVERIFIED (§2.0, Q2) — the single most important contract is a hole.
SCB — Scope Boundaries8.5Repo Map (§2.0) names every file with create/modify/read tags; non-goals explicit (§1.3); "CRM frontend repository only" scope guard at top; per-story change map (Detail 1.C) lists exact paths. Agent can produce file-by-file plan.
DEP — Dependencies6.5A&L deps (SM, Redis, Kong) named and bounded; reused CRM endpoints verified with line numbers. Docked: @mekari/sdk registry availability unconfirmed (Q6) blocks chunk 1; verified absent from current package.json.
FMC — Failure Mode Coverage7.0server_down fallback fully drawn (§2.5 failure seq + §2.6 state machine); fail-closed toggle-read (§2.7); cross-origin logout path diagrammed. Docked: no error-message catalog/i18n keys; only one toast string in prose; toast component API unconfirmed (Q5).
NFS — Non-Functional Specificity6.5postMessage origin validation mandated (§3.1); SDK init explicitly non-blocking (§3.3); security threat (iframe/CSP) modeled. Docked: CSP delivery mechanism unconfirmed (Q8); no quantified perf budget (acceptable for an integration enhancement).
TPS — Test Plan Specificity7.5Per-chunk assertable criteria (§4.C); per-event test list (§2.4 → chunk 4); named spec files (tests/plugins/mekari-session.spec.js). Failure paths in scope. Docked: no explicit a11y/keyboard test for the toast surface.
ROL — Rollout & Rollback8.04 staged rollout with go/no-go evidence (§4.A); numbered agent-executable rollback (§4.D) with toggle-off as instant primary lever; pre-merge command list verified against package.json (§4.B). Config contract = the toggle.
OBS — Observability7.5Named RUM action mekari_session.event + error on server_down and origin-mismatch (§3.2); reuses plugins/datadog-rum.js convention; post-deploy signals enumerated (§4.D).
CPA — Pattern Alignment8.5"Patterns to Follow" table (§2.0) maps every concern to a reference file; reuses userLogout, datadog-rum init, custom_features read, window.location.href redirect convention. Explicitly avoids new patterns. Strong for an enhancement.

Decision Closure Assessment

Decision Index

#DecisionStatusCritical Gaps
D1SDK delivery (npm @mekari/sdk + Nuxt plugin)PartialRegistry availability unconfirmed (Q6)
D2Feature gating via custom_features code centralized_sessionPartialExact code string unverified (Q3)
D3SDK mount point + event wiring (plugin after auth)ResolvedSPA route-change refresh hook noted but not fully specified
D4logged_out/server_down → reuse userLogout + SSO redirectResolvedImpact on other userLogout callers open (Q7, important)
D5switch_user → interim sign-out + toastDanglingReal seamless flow unresolved (Q1 critical); SSO-autologin contract unknown
D6msli localStorage fallback helperResolvedNone — fully specified
D7current_company syncDanglingDeferred; no CRM endpoint/field exists (Q4 critical)

Aggregate: 3 of 7 Resolved (D3, D4, D6), 2 Partial (D1, D2), 2 Dangling (D5, D7).


Decision: D5 — switch_user action under CRM's token model

Status: Dangling

What was decided

Interim: treat switch_user as full sign-out + "user has changed" toast + re-login; seamless SSO-autologin path deferred (ADR-5, §2.4).

Alternatives considered

(a) Full SSO-autologin round-trip — rejected: needs SSO callback route + token re-issue CRM lacks. (b) Interim sign-out — chosen. (c) Silent token swap — rejected: no mechanism, security risk. Genuine evaluation, tied to codebase reality (crm-user redirects to crmV1Host/login).

Grounding in existing code

Grounded: schemes/crmAuthScheme.js (token model), middleware/crm-user.js (redirect target), store/user.js:userLogout. Strong.

Interface specification

Interim path fully specified (reuse userLogout + toast + redirect). Seamless path UNSPECIFIED — the SSO-autologin contract for token products does not exist in-repo.

Failure handling

Interim path degrades cleanly (user re-logs in). No silent failure.

Challenge results

  • Scale: Holds — per-user event, no shared-resource contention.
  • Reversibility: High — upgradeable to seamless when contract defined.
  • Consistency: Consistent with D4 (both end at account.mekari.com/sign_out).
  • Agent implementability: Agent CAN build the interim path. Agent CANNOT build the seamless path — would hallucinate the SSO callback.

Gaps and suggestions

Missing: SSO-autologin contract for CRM's token model; whether interim UX is product-accepted. Suggested resolution: Ship interim behind toggle; open a follow-up ticket against A&L for the token-product autologin contract; get product sign-off on the re-login UX before GA. Open questions for the author: Q1 — which PRD flow applies to a token-based product, and what is the autologin callback contract?


Decision: D7 — current_company sync

Status: Dangling

What was decided

Defer — out of FE-deliverable scope; CRM uses teams, no current_company endpoint found (ADR-7, §5 Q4).

Alternatives considered

(a) Implement once BE exposes endpoint; (b) map to CRM team context; (c) defer — chosen. Evaluated against verified absence of any current_company field (only /users/crm_teams, /crm/teams found, store/user.js:244,261,274).

Grounding in existing code

Grounded in the absence — Source Verification marks it UNVERIFIED/absent. Correct anti-hallucination posture.

Interface specification

N/A — deferred; no interface invented.

Failure handling

After interim sign-out + re-login, company context resolves via CRM normal login — acceptable interim behavior.

Challenge results

  • Reversibility: N/A (deferred).
  • Consistency: Consistent — relies on D5 interim re-login.
  • Agent implementability: Agent correctly does nothing here; building it would require inventing a contract.

Gaps and suggestions

Missing: Whether CRM even has a per-company switch equivalent; need for a BE RFC. Suggested resolution: Confirm with CRM BE whether current_company maps to a team-context switch; if a real need exists, raise a separate BE RFC and link it in S4. Open questions for the author: Q4 — is a BE RFC required, and what is CRM's company-context equivalent?


Decision: D1 — SDK delivery into CRM

Status: Partial

What was decided

npm @mekari/sdk imported in new plugins/mekari-session.js (ADR-1), over a <script src> runtime tag.

Alternatives considered

(a) npm + plugin — chosen (matches PRD import form, plugin pattern, testability). (b) script tag — rejected. Reasoned.

Grounding in existing code

Grounded in plugins/datadog-rum.js pattern + nuxt.config.js:58 registration.

Interface specification

Plugin shape specified. Constructor input incomplete — depends on Q2 (user_sso_id).

Failure handling

Toggle off / read error → fail-closed (SDK not loaded), no regression. Good.

Challenge results

  • Reversibility: High — remove plugin + dep, toggle off.
  • Agent implementability: Cannot run yarn add @mekari/sdk until registry confirmed (Q6).

Gaps and suggestions

Missing: Confirmed registry availability + pinned version. Suggested resolution: Verify package in Mekari private npm registry; pin version in chunk 1 before any other chunk. Open questions for the author: Q6.


Decision: D2 — Feature gating

Status: Partial

What was decided

Reuse custom_features from /users/me/feature_enabled, check code centralized_session (ADR-2).

Alternatives considered

(a) reuse custom_features — chosen; (b) env flag; (c) packageFeatures entry — both rejected with server-rollout rationale.

Grounding in existing code

Grounded: store/user.js:67 getCustomFeature, middleware/redirect-to-v3.js:49 read pattern. Strong.

Interface specification

Read mechanism specified. Exact code string unverified (Q3) — format ambiguity between CP-QONTAKCRM-YYYY-NNNN and plain string codes (e.g. use_central_contact_data).

Failure handling

Fail-closed on read error — SDK not loaded. Good.

Challenge results

  • Reversibility: High — server toggle.
  • Agent implementability: Agent would guess the code string; left as placeholder (correct, but blocks the gate test).

Gaps and suggestions

Missing: Exact centralized_session code value. Suggested resolution: Confirm with backend toggle owner; until then, parameterize the code as a constant in assets/variables/ so the guess is single-sourced. Open questions for the author: Q3.


UI State Audit

One user-visible surface (toast). Other "states" are session behaviors, not data-driven components.

ComponentLoadingEmptyErrorPartialSuccessAssessment
switch_user toastn/an/amissingn/adefined ("user has changed")1/2 applicable — toast failure-to-render path not addressed; exact copy/i18n key + component API unconfirmed (Q5)

Summary: The RFC is behavior-centric (events → store/nav), not screen-centric, so the 5-state model maps weakly. The single rendered surface lacks an i18n key and a confirmed component contract.


Performance Budget Check

MetricTargetCurrent BaselineSourceAssessment
LCP / INP / CLSnot statednot statedNot specified — acceptable: §3.3 commits to non-blocking async SDK init, no render-path change
Bundle size deltanot statedMissing — adding @mekari/sdk introduces a dep with unquantified size; add a budget note in chunk 1

Assessment: NO QUANTIFIED PERFORMANCE BUDGET — low impact for this sub-type since SDK init is async/non-blocking, but the bundle delta of @mekari/sdk should be measured at chunk 1.


Accessibility Review

AspectSpecified?DetailsAssessment
Keyboard navigationnoN/A — no new interactive surface beyond toast
Focus managementnoMissing — switch_user toast appears before forced sign-out; focus/announce behavior undefined
ARIA / screen readernotoast not specifiedMissing — confirm toast uses an aria-live region (defer to user-notifications skill, Q5)
Color contrast / motionnoreuses existing notificationAssumed inherited from design system

Assessment: Minimal a11y surface, but the switch_user toast must announce via aria-live since it precedes an involuntary sign-out — note this in chunk 4.


Pattern Alignment Check

PatternRFC ApproachAssessment
Third-party SDK initfollows (plugins/datadog-rum.js)Strong — conditional gate, default-export init fn
Feature-flag readfollows (middleware/redirect-to-v3.js:49)Strong — same custom_features.find shape
Sign-out orchestrationextends (store/user.js:userLogout)Good — adds SSO redirect to existing path; verify other callers (Q7)
External redirectfollows (window.location.href)Strong — matches version-switcher convention
Observabilityfollows (@datadog/browser-rum)Strong — reuses service convention
msli storagecreates (new helper)Justified — new artifact, isolated + unit-testable

Assessment: Excellent pattern adherence; only one new pattern (msli helper), and it's justified and isolated. No parallel-system risk.


Cross-Layer Note (frontend RFC — out of scope by design)

The SSO/Session Manager/Redis/Kong-MAG layers are A&L-owned and READ-ONLY here (scope guard). Two cross-layer dependencies leak into FE readiness and are correctly flagged: the account.mekari.com CSP frame-ancestors whitelist must include CRM's domain before stage-1 pilot (§4.A), and the SSO-autologin contract (Q1) and current_company endpoint (Q4) are BE/SSO prerequisites for the deferred paths.


Agentic Readiness Deep-Dive

Vague Word Audit

#Word/PhraseLocationImpactConcrete Replacement
1"throttled" session.refresh()§2.2, ADR-3, Q9Agent guesses intervalDefine: time-based (e.g. ≤1/min) vs per-navigation; Q9 acknowledges this
2"[REQUIRED field — §5 Q2]" user_sso_id§2.2Agent cannot fill SDK inputPin exact $auth.user.<field> path
3"[REQUIRED: confirm component]" toast§2.0 PatternsAgent invents toast APIName the components/_general/ notification component + i18n key

Total vague words in spec sections: 3 (each already cross-linked to an open question — good hygiene).

Dangling Alternatives

#AlternativesLocationImpact
1switch_user: full autologin vs interim sign-outADR-5 / Q1Agent builds interim only; seamless path absent
2current_company: implement vs map-to-team vs deferADR-7 / Q4Agent does nothing (correct)

Total dangling alternatives: 2 (both critical-tagged and consciously deferred, not accidentally left open).

Task Decomposition Assessment

ChunkAcceptance CriteriaAssessment
2 msli helpermsli<2h+cookie→logged_in; >2h/no cookie→logged_out; missing→server_downverifiable
3 plugin + gatetoggle off→no Session; on→Session w/ user_sso_id; origin validatedverifiable (but blocked on Q2 for the user_sso_id assertion)
4 event handlersper-event tests; msli cleared on logoutverifiable
5 logout→SSO redirectafter sign_out resolves, window.location.href setverifiable
6 observabilityRUM action emitted (mock datadogRum)verifiable
1 add depdep present, frozen-lockfile passesblocked on Q6

Assessment: Strong decomposition with dependency ordering stated (§4.C). Chunks 2, 3 (scaffold), 6 executable now; 1, 4, 5 gated on critical answers.


Strengths

  • Source Verification table (§2.0) separates verified anchors (with file:line) from UNVERIFIED unknowns — the single best agentic-readiness feature in this RFC; it converts unknowns into explicit blockers instead of silent guesses.
  • Reuse-first pattern alignment (§2.0 Patterns, ADR-4) — every concern maps to an existing file (userLogout, datadog-rum, custom_features), so generated code will look native to the codebase.
  • Numbered, toggle-first rollback recipe (§4.D) with server-side toggle-off as the instant primary lever and PR revert as secondary — executable without the author.

Biggest Gaps

  • user_sso_id source UNVERIFIED (§2.0, §2.2, Q2) — the SDK constructor input has no confirmed field on /users/me; only company-level external_company_id is verified. Without it the entire integration object is a guess. Blocks chunks 1, 3, 4.
  • switch_user real flow unresolved (ADR-5, Q1) — CRM is token-based with no SSO-autologin callback; only an interim sign-out is buildable. The PRD's headline "seamless switch" behavior cannot be implemented from this RFC.
  • centralized_session exact code + @mekari/sdk registry (Q3, Q6) — the feature-gate string is a placeholder and the npm package is unconfirmed in the registry, so chunk 1 (yarn add) and the gate test cannot be authored deterministically.

Priority Actions

  1. Q2 / §2.0 Source Verification — Confirm the exact field exposing the user's SSO id in the /users/me (crmAuthScheme.fetchUser) response and pin it in §2.2. Unblocks SDK construction and every event comparison; without it chunks 3 and 4 are guesses.
  2. Q1 / ADR-5 — Get product sign-off on the interim sign-out UX and open a follow-up against A&L for the token-product SSO-autologin contract. Lets chunk 4's switch_user handler ship without inventing a callback.
  3. Q3 / ADR-2 — Confirm the literal centralized_session feature code with the toggle owner; store it as a single constant. Unblocks the gate test in chunk 3.
  4. Q6 / chunk 1 + Q5 / §2.0 — Verify @mekari/sdk registry availability + pin version, and confirm the components/_general/ toast component API + i18n key for "user has changed." Unblocks chunk 1 and the chunk-4 toast.

Implementation Readiness Checklist

Unblocked (agent can proceed)

  • PRD → RFC traceability matrix present (Detail 1.A)
  • Scope boundaries / file list pinned (§2.0 Repo Map, Detail 1.C)
  • Pattern alignment verified (§2.0 Patterns)
  • Rollout plan + rollback mechanism (§4.A, §4.D)
  • Observability metrics named (§3.2)
  • Task decomposition with per-chunk acceptance criteria (§4.C)
  • msli fallback + server_down failure path specified (ADR-6, §2.5)
  • Config contract: centralized_session toggle, fail-closed default

Blocked (must fix first)

  • user_sso_id source unverified — SDK constructor input cannot be filled (Q2, critical)
  • switch_user seamless flow unresolved for token model (Q1, critical)
  • current_company sync deferred with no contract (Q4, critical)
  • centralized_session exact code unverified (Q3, critical)
  • @mekari/sdk registry availability + toast component API unconfirmed (Q6, Q5)

Verdict: Fix 4 critical blockers (Q1–Q4) first — chunks 2, 3 (scaffold), 6 may proceed in parallel.


Task Manifest

RFC specifies decomposition in §4.C; verified and reproduced with readiness tags.

OrderChunkFiles to Create/ModifyAcceptance CriteriaDependencies
1Add dependencypackage.json, yarn.lock@mekari/sdk pinned; yarn install --frozen-lockfile passesBlocked on Q6
2msli fallback helperutils/helpers/mekari-session.js, tests/utils/helpers/mekari-session.spec.jsmsli<2h+cookie→logged_in; >2h/no cookie→logged_out; missing→server_downNone — executable now
3SDK plugin + toggle gateplugins/mekari-session.js, nuxt.config.js, tests/plugins/mekari-session.spec.jstoggle off→no Session; on→Session built; event.origin validatedChunk 2; user_sso_id assertion blocked on Q2
4Event handlersplugins/mekari-session.js, store/user.js (clear msli in deleteUserLocalData)per-event tests pass per §2.4Chunk 3; switch_user blocked on Q1; toast on Q5
5Logout → SSO redirectstore/user.js:userLogoutafter sign_out resolves, window.location.href = account.mekari.com/sign_outVerify other callers (Q7)
6Observabilityplugins/mekari-session.jsRUM mekari_session.event emitted (mock datadogRum)Chunk 3

RFC SPECIFIES decomposition — verified against package.json scripts; no invention needed.


Dangling Decisions Log

#DecisionLocationOwnerDeadline
1switch_user seamless flow (token model)ADR-5 / Q1A&L (SSO) + CRM FEbefore GA
2current_company syncADR-7 / Q4CRM BE + A&Lbefore GA (or confirm not needed)
3centralized_session exact codeADR-2 / Q3Toggle ownerbefore chunk 3 test
4@mekari/sdk registry availabilityADR-1 / Q6A&L (SDK)before chunk 1

Open Questions

#QuestionCategorySeverity
1Which PRD flow applies to CRM's token model; SSO-autologin contract?TDCBlocking
2Source of user_sso_id in /users/me?CNTBlocking
3Exact centralized_session feature code string?DEP / CNTBlocking
4current_company CRM equivalent; BE RFC needed?TDCBlocking
5Exact toast component API + i18n key?FMC / a11yImportant
6@mekari/sdk published to private registry?DEPImportant
7Do existing userLogout callers break with SSO redirect?FMC / CPAImportant
8CSP delivery mechanism (edge vs meta)?NFSImportant
9session.refresh() throttle interval?NFSNice-to-have

Evidence Notes

  • §2.0 Source Verification — strongest evidence; verified anchors carry file:line, and three rows are explicitly UNVERIFIED (user_sso_id, current_company, feature code). Drove the CNT (5.5) and TDC (6.0) scores and the HOLD verdict.
  • §4.C Agent Execution Plan + §4.B commands — assertable acceptance criteria tied to real package.json scripts lifted TPS (7.5) and ROL (8.0).
  • §5 Open Questions — four [critical] items map cleanly to the §7 failing gates; their presence is why this scores Needs Work rather than Insufficient — the gaps are identified, not hidden.
  • §1.4 / §2.0 toast component — absence of a confirmed notification component API and i18n key held FMC at 7.0 and surfaced the a11y aria-live gap.