Skip to main content

RFC Review: Centralized Web Session — Hub Chat v2 FE Integration

Executive Summary

  • Overall Score: 6.5/10
  • Rating: Needs Work
  • RFC Type: frontend
  • Sub-Type: enhancement
  • Assessment Confidence: High
  • Applied Caps/Gates: FMC < 7.0 gate (no error-message catalog) holds FMC at 6.5; CNT < 7.0 gate (data/SDK contract incomplete) holds CNT at 6.5. No hard overall cap triggered — overall set by judgment: two [critical] blockers prevent end-to-end agent execution.
  • Implementation Readiness Verdict: HOLD — blockers Q1 (cross-domain fallback) and Q2 (SDK availability) must be closed before any chunk runs
  • Report Path: /Users/mekari/Documents/hub-chat-v2/rfc-review-report.md
  • RFC Author: syafrizal.abdillah@mekari.com | Reviewed: 2026-06-28

This RFC is among the best-anchored FE integration documents in this repo: every claim is grounded in a verified file:line, the scope is file-by-file, and the agent execution plan is ordered with assertable acceptance criteria. An AI agent could implement Chunks 1–6 almost verbatim if its two upstream dependencies existed. They do not yet: @mekari/sdk is absent from the repo and unverified (grep confirms — present only in docs), and the cross-domain _mekari_account fallback may be structurally impossible for the qontak origin. The single thing that must change before agentic execution: resolve Q2 (publish/confirm the SDK package + its exact interface) and Q1 (lock the fallback contract boundary). The biggest strength is scope+pattern discipline; the biggest gap is that the load-bearing external contract (the SDK API surface) is unverified.


Quick Verdict

Why this RFC can be implemented agentically:

  • Every chunk in §4.C names exact files, mock strategy (vi.mock @mekari/sdk), and assertable acceptance criteria.
  • Decisions are closed as 7 ADRs (§2.6) with options, rejection rationale, and reversibility; all anchored to real code (AuthStore.ts:42, AppConfigStore.ts:2, verified).
  • Rollout/rollback (§4.A/§4.D) is concrete: flag default off, numbered rollback, RUM verification signals.

Why this RFC will cause agent guessing or rework:

  • @mekari/sdk Session API is not pinned — §2.1 is explicitly "shape, not final code"; the event-subscription mechanism, constructor return, and teardown are unknown (Q2 [critical]).
  • The msli/server_down soft-grace depends on Q1, which the RFC itself flags as possibly "structurally impossible" — an agent would implement a fallback that may be invalid.
  • No error-message strings/i18n keys; the only user-facing copy ("user has changed") is TBD (Q6).

PRD → RFC Traceability Matrix

Parent cross-product RFC (Confluence) is the authoritative PRD. It was not machine-readable for this review; mapping assessed against the in-RFC §1.A coverage table, which itself enumerates parent-RFC sections.

Standard format (PRD exists)

PRD Element (parent-RFC section)RFC SectionCoverage
Overview / Success Criteria§1.0, §1.AFull
Proposal / SDK usage§2.1, §2.2Partial — SDK init shape present, concrete API unverified (Q2)
SDK contract (4 events)§2.2 event→action mapFull
FE Integration Flows (SDK flow)§2.3 diagramsFull
FE Integration Flows (Web Session / current-company)§2.2, §2.3, §2.6-A7Partial — ownership of current_company sync unresolved (Q4)
OAuth2 auth-code flow§2.2, §2.6-A6Full — reuses /sso-callback
User Logout From Product§2.4Full — already implemented, verified pages/logout.vue:315
User Switch Account§2.2, §2.3, §2.6-A6Full
HA & Security§3Full (FE share)
Rollout Plan§4Full — hub-chat is step 5, not first pilot
Open Questions§5Full + FE-specific blockers added
Local Storage msli / cookies§2.2, §5 Q1Partial — cross-domain conflict unresolved (Q1 [critical])
Database Modeln/a — no DB (FE repo)
Multiple sessions per accountn/a — server/SSO concern
Out-of-scope: auto token revoke on idle§1.AFull — carried verbatim

Summary: ~11 of 14 parent items fully covered, 3 partial (all tied to open questions Q1/Q2/Q4), 0 silently dropped. No RFC decision lacks a parent-RFC driver — zero scope creep. PRT is strong; the partials are upstream-owned, not authoring gaps.


Scorecard

Frontend Scorecard (11 categories)

CategoryScoreEvidence-Based Rationale
PRT — PRD Traceability8.0§1.A forward+reverse matrix, UI/role/lifecycle sub-tables. Reverse traceability explicit ("no RFC decision without PRD driver"). Capped under 9 only because parent PRD not directly verifiable here.
TDC — Technical Decisions8.07 ADRs (§2.6) with options/rejection/reversibility. Deductions: D5 server_down=/logout is "suggested" (inherits parent uncertainty); D7 depends on Q4.
CNT — Contract Specificity6.5event→action map (§2.2) and msli shape are clear, but SDK API itself "shape, not final code" (§2.1); no TS interface for the SDK, subscription, or teardown. Data-fetching = store refetch (OK). Gate: <7.0 because SDK contract unpinned.
SCB — Scope Boundaries9.0§2.0 Repo Map + §4.C chunks name every file to create/modify; non-goals explicit (§2.4 "already implemented", §1.A n/a rows). Agent can produce file-by-file plan directly.
DEP — Dependencies5.0@mekari/sdk unverified — no version/registry/entry (Q2 [critical], grep-confirmed absent). BE flag + BE current_company are external deps named with status. Honest but the core dep is a hard blocker.
FMC — Failure Mode Coverage6.5Covers server_down, origin-mismatch ignore, soft-grace, switch_user redirect (§2.2/§2.3). Gate: <7.0 — no error-message catalog; toast copy TBD (Q6); no per-HTTP-status UI behavior for the refetch calls.
NFS — Non-Functional Specificity6.0Security strong (§3.3 OWASP-mapped: postMessage origin, CSP, no-token-in-logs). But perf throttle "TBD" (Q3), no browser matrix, a11y not addressed (toast focus/SR), i18n copy TBD.
TPS — Test Plan Specificity8.0§4.C per-chunk assertable acceptance (e.g. "postMessage mismatched origin is ignored", "SDK NOT constructed when toggle off"). Maps to vitest commands. Missing: explicit failure-path E2E naming.
ROL — Rollout & Rollback8.5Flag default off (§4.A), numbered agent-executable rollback (§4.D), config contract = centralized_session flag, verification signals via RUM. hub-chat sequenced as step 5 behind Launchpad.
OBS — Observability7.53 named RUM actions w/ thresholds (§3.4); no-token payload rule. Deduction: action names unconfirmed (Q7); no dashboard/alert wiring named.
CPA — Pattern Alignment9.0§2.0 "Patterns to Follow" mirrors datadog.client.ts, seamless_auth_first gating (verified AppConfigStore.ts:7), useEventBus, pages/logout.vue reuse. Code will look native.

Caps applied: CNT and FMC held below 7.0 by rubric "must be present for >=7.0" gates (data/SDK contract; error-message catalog). No overall hard cap fired (no category <5.0; DEP exactly 5.0). Overall set by judgment at 6.5: two [critical] blockers make end-to-end agent execution impossible today, despite high authoring quality.


Decision Closure Assessment

Decision Index

#DecisionStatusCritical Gaps
D1SDK init in plugins/mekariSession.client.tsResolvednone
D2Gate via AppConfigStore.centralized_sessionResolvednone
D3useCentralizedSession + useEventBus deliveryResolvedsession:* bus keys "only if needed" — slightly open
D4current_user = user.sso_idResolvednone (verified AuthStore.ts:42)
D5logged_out/server_down/logoutPartialserver_down is "suggested"; soft-grace depends on Q1
D6switch_user → reset → /sso-callback re-authResolvednone
D7Current-company = refetch org+company storesPartialdepends on BE setting current company (Q4)
DxSDK package identity + API surfaceDanglingQ2 [critical] — package unverified
DyCross-domain _mekari_account fallback boundaryDanglingQ1 [critical] — possibly impossible

Aggregate: 5 Resolved, 2 Partial, 2 Dangling.


Decision: Dx — SDK package identity & API surface

Status: Dangling

What was decided

"Add @mekari/sdk Session SDK, load with sso_id" (§1.C). §2.1 gives only a sketch: new Session({ current_user: sso_id }), labeled "shape, not final code".

Alternatives considered

NO ALTERNATIVES — it is an external mandated dep from the parent RFC. Acceptable (no choice to make), but the integration mode (bundled vs CDN) is decided (§3.1 bundled, pinned) — good.

Grounding in existing code

NOT GROUNDED — grep @mekari/sdk returns only docs (verified). Agent must add the dep blind.

Interface specification

INCOMPLETE. Missing: package name on registry, version, CJS/ESM entry, constructor signature, how events are subscribed (callback? .on()? returned emitter?), teardown/destroy(), session.refresh() signature.

Failure handling

Partial — server_down mapped, origin-check specified. But what if new Session() throws / SDK fails to load? Not specified.

Challenge results

  • Scale: n/a (single client instance).
  • Reversibility: high — delete plugin+composable+dep.
  • Consistency: consistent with *.client.ts precedent.
  • Agent implementability: NO — agent cannot pnpm add an unverified package nor write vi.mock matching an unknown surface. Would guess the event API → rework.

Gaps and suggestions

Missing: registry/access, version, entry format, event-subscription API, teardown. Suggested resolution: A&L publishes @mekari/sdk@x.y.z (or pre-release) with a typed Session interface; paste the .d.ts excerpt into §2.2. Until then, stub a local types/mekari-sdk.d.ts contract so Chunks 2–3 can proceed against a frozen interface. Open questions: Q2.


Decision: Dy — Cross-domain _mekari_account fallback boundary

Status: Dangling

What was decided

hub-chat consumes SDK events + its own msli; _mekari_account evaluated only inside SDK/iframe (§2.2). Flagged as possibly "structurally impossible" if hub-chat is expected to read the mekari cookie.

Grounding in existing code

Grounded in memory sso-cross-domain-cookies + COOKIE_DOMAIN=.qontak.com (verified claim in §2.0). The constraint is real.

Interface specification

INCOMPLETE — msli write/read is specified; the grace-vs-force decision logic at server_down is conditional on Q1's answer.

Failure handling

Partial — soft-grace path drawn (§2.3 failure diagram) but its validity is unconfirmed.

Challenge results

  • Reversibility: medium — fallback logic touches the forced-logout path; wrong assumption = users wrongly signed out or wrongly kept in.
  • Consistency: consistent with cross-tab logout precedent (app.vue:216, verified).
  • Agent implementability: NO — agent would implement a grace window that A&L may reject. Must wait on Q1.

Gaps and suggestions

Missing: authoritative statement of which origin evaluates _mekari_account. Suggested resolution: A&L confirms iframe-only evaluation in writing; then hub-chat implements msli-only grace exactly as §2.3. If hub-chat must read the cookie → redesign required. Open questions: Q1.


Decision: D5 — logged_out/server_down/logout

Status: Partial logged_out/logout is fully resolved (verified pages/logout.vue:315). server_down mapping is "suggested" and entangled with the Q1 soft-grace. Close by confirming the grace policy.

Decision: D7 — Current-company sync via store refetch

Status: Partial Reuse of OrganizationStore.getDetail() + CompanyStore.getCompanyDetail() is sound, but correctness depends on hub-core setting current company server-side before refetch (Q4). If not, refetch returns stale company → silent wrong-org bug.


UI State Audit

This enhancement adds essentially no new data-driven component (SDK iframe invisible; reuses existing screens).

ComponentLoadingEmptyErrorPartialSuccessAssessment
Re-auth loading (CommonSsoCallbackLoading)reusedn/amissingn/areused3/5 — no error state if /sso-callback re-auth fails post switch_user
"User has changed" toastn/an/an/an/adefined (copy TBD)1/1 — copy is Q6
Org/company refetch (background)not definednot definednot definednot definedimplicit0/5 — refetch failure after logged_in/switch_user has no defined UI

Summary: The refetch-failure path (org/company store rejects after logged_in/switch_user) has no specified UI state. Add: on refetch error, behavior = retry? force logout? toast? Currently agent would leave a silent stale-org state.


Performance Budget Check

MetricTargetCurrent BaselineSourceAssessment
SDK init blocking"must not block first paint"not stated§3.2qualitative only — no ms target
session.refresh() cadenceTBDexisting 1s tick (AuthStore.ts:509)§3.2 / Q3MISSING — throttle interval unresolved, risk of hammering sm/current
Bundle size delta (SDK bundled)not stated§3.1MISSING — SDK is bundled (§3.1) but no kB budget
LCP / INP / CLSnot statedn/a for this change, but bundle delta should be tracked

NO QUANTIFIED PERF BUDGET for the one real perf lever (bundle delta from a bundled SDK + refresh cadence). Add a bundle budget once SDK size known (depends on Q2).


Accessibility Review

AspectSpecified?DetailsAssessment
Keyboard navigationnoreuses existing redirect/logoutacceptable — no new interactive surface
Focus managementnotoast via notification:showincomplete — toast focus/SR announcement not specified
ARIA labelsnon/a — no new custom controls
Heading hierarchyn/an/a
Color contrastn/areuses Pixel toastinherits Pixel
Motion sensitivityn/an/a
Screen readerno"user has changed" toastincomplete — confirm toast is announced (aria-live) via Pixel default

Low blast-radius (reuses existing screens). Only gap: confirm the reused Pixel toast announces to SR; otherwise no a11y action needed.


Pattern Alignment Check

PatternRFC ApproachAssessment
Feature-flag gatingfollows seamless_auth_first (verified AppConfigStore.ts:7)aligned
Client-only bootfollows *.client.ts (datadog precedent)aligned
Cross-feature eventsreuses useEventBus/AppEventMap (plugins/eventBus.ts:6)aligned
Forced logoutreuses pages/logout.vue rather than re-implementingaligned — avoids parallel cleanup path
Store error handling"mirror CompanyStore.ts"aligned but unspecified — which error pattern exactly?
Datadog RUMfollows datadogRum.setUser (app.vue:152)aligned; action naming is new (Q7)
Analytics events preservedno existing events droppedaligned

Strongest dimension. No parallel systems introduced.


Data Flow Trace

Flow: switch_user

SDK postMessage (different user_sso_id)
→ useCentralizedSession: verify event.origin === account.mekari.com [§3.3]
→ authStore.resetAuthStore() [verified pattern]
→ navigateTo(account.mekari.com/auth?return_to=/sso-callback)
→ /sso-callback?code=... → runSsoCallback → performSsoSignIn [middleware/sso-callback.ts:541, verified]
→ refetch OrganizationStore.getDetail() + CompanyStore.getCompanyDetail()
→ eventBus notification:show "user has changed" [copy TBD — Q6]
→ UI: home

Gaps in flow: (1) refetch-failure branch undefined; (2) current-company correctness assumes BE pre-set (Q4); (3) re-auth failure at /sso-callback has no defined recovery.


Strengths

  • Scope + grounding discipline (§2.0, §4.C): every anchor is a verified file:line (spot-checked AuthStore.ts:42 sso_id ✓, AppConfigStore.ts:7 seamless_auth_first ✓, @mekari/sdk absent ✓). Agent can navigate without searching.
  • Decision closure as ADRs (§2.6): 7 decisions with options, rejection rationale, reversibility — well above repo norm.
  • Rollout/rollback realism (§4.A/§4.D): dark-by-default flag, numbered agent-executable rollback, RUM verification signals, correct sequencing behind Launchpad.
  • Self-aware blocker honesty (§5/§7): the RFC flags its own [critical] gaps and refuses to set status:yes — exactly right.

Biggest Gaps

  • DEP/Q2 — @mekari/sdk unverified (§5 Q2, grep-confirmed): the single load-bearing dependency has no version/registry/interface. Every code chunk (esp. 2,4) is non-compilable until resolved. This caps real-world readiness regardless of authoring quality.
  • CNT/Q1 — cross-domain fallback may be structurally impossible (§2.2, §5 Q1): if hub-chat is expected to read _mekari_account, the design breaks; agent would build an invalid fallback.
  • FMC — no error-message catalog + undefined refetch-failure UI (§1.D, UI State Audit): toast copy TBD; org/company refetch failure has no specified behavior → silent stale-org risk.

Priority Actions

  1. Q2 / Decision Dx — A&L publishes/confirms the @mekari/sdk package (name, version, registry access) and pastes the Session .d.ts (constructor, event subscription, refresh(), teardown) into §2.2. Unblocks Chunks 2–4 compilation and vi.mock fidelity.
  2. Q1 / Decision Dy — Get written confirmation that _mekari_account is evaluated only inside the SDK/iframe; freeze the msli-only grace policy in §2.2. Unblocks Chunk 3 correctness.
  3. FMC — Add an error-message catalog: the "user has changed" toast string/i18n key (Q6) and the behavior on org/company refetch failure (retry vs forced logout vs toast). Unblocks Chunk 3 + UI State completeness.
  4. Q4 + Q3 — Confirm hub-core sets current_company server-side before refetch (else add explicit FE call), and pin the session.refresh() throttle interval. Removes the two remaining behavioral guesses.

Implementation Readiness Checklist

Unblocked (agent can proceed)

  • PRD → RFC traceability matrix complete (§1.A)
  • Rollout plan with feature flag + rollback (§4.A/§4.D)
  • Observability metrics defined (§3.4, naming pending Q7)
  • Task decomposition with acceptance criteria per chunk (§4.C)
  • Pattern alignment verified (§2.0)
  • Configuration contract: centralized_session flag, default off
  • All interfaces/prop types fully specified — SDK API not pinned
  • All UI states defined — refetch-failure + re-auth-failure states missing
  • Performance budget quantified — refresh throttle + bundle delta missing
  • Zero vague words — "suggested" (server_down), "TBD" (throttle, copy, naming)

Blocked (must fix first)

  • Q2 — @mekari/sdk Session package + interface unverified (no chunk compiles)
  • Q1 — cross-domain _mekari_account fallback semantics undefined (possible structural impossibility)
  • Q8 — approvers incl. mandatory infosec unassigned (CSP/iframe/postMessage)

Verdict: Fix 2 blockers first (Q1, Q2) — plus assign infosec approver (Q8) before sign-off.


Task Manifest

Verifying the RFC's own §4.C decomposition — it is sound; reproduced with dependency notes.

OrderChunkFiles to Create/ModifyAcceptance CriteriaDependencies
1Feature flagcommon/store/AppConfigStore.ts (+centralized_session?), __tests__/AppConfigStore.spec.tstype-check passes; field reads, undefined→offNone
2useCentralizedSession + SDK lifecycle (TDD)common/composables/useCentralizedSession.ts (+spec)SDK constructed w/ current_user===sso_id; mismatched origin ignored; msli written on logged_inQ2 (SDK interface)
3event→action map (TDD)extend composable + speclogged_out/server_down/logout; switch_user→reset+redirect; logged_in→refetchQ1, Q4, Q6
4Plugin wiring (client-only)plugins/mekariSession.client.ts (+spec)SDK starts only when flag ON ∧ authed ∧ sso_idChunk 1,2; Q2, Q5
5Observability/RUMcomposable (+spec)RUM action per event, no token/sso_id in payloadChunk 3; Q7
6Docsdocs/architecture/flows/login/README.md and/or auth-sso/README.mdspoke updated, status: ready, diagram addedChunk 1–5

RFC specifies this decomposition; verified executable in order once Q1+Q2 close.


Dangling Decisions Log

#DecisionLocationOwnerDeadline
1@mekari/sdk Session package identity + API surface§2.1, §5 Q2Account & Launchpadunset
2Cross-domain _mekari_account fallback boundary§2.2, §5 Q1A&L + Platformunset
3server_down final action (vs "suggested") + soft-grace policy§2.6-A5, §2.2Platform (post Q1)unset
4Current-company sync ownership (FE call vs BE pre-set)§2.6-A7, §5 Q4hub-core + A&Lunset

Open Questions

#QuestionCategorySeverity
Q1Is _mekari_account evaluated only inside SDK/iframe (hub-chat consumes events+msli only)?TDC/FMCBlocking
Q2@mekari/sdk package name, registry/access, version, CJS/ESM entry, event API?DEP/CNTBlocking
Q3Agreed session.refresh() throttle interval?NFSImportant
Q4Does hub-core set current_company server-side before refetch, or must FE call SSO?TDCImportant
Q5Does centralized session apply to super_admin (today bypasses billing/MQTT)?SCB/CPAImportant
Q6"Your account has changed" toast copy/i18n key?FMCImportant
Q7Datadog custom action naming convention?OBSNice-to-have
Q8Assign approvers incl. mandatory infosec?ROL/SecurityImportant

Evidence Notes

  • §2.0 Existing Code Anchors / Source Verification — spot-checked and confirmed: AuthStore.ts:42 sso_id ✓, AppConfigStore.ts:2/7 AppConfig+seamless_auth_first ✓, @mekari/sdk absent from code (docs-only) ✓, listenForLogout present ✓. Raised PRT/CPA/SCB scores.
  • §5 Concerns — Q1 and Q2 self-flagged as [critical]; this is why overall is HOLD despite high authoring quality. Drove DEP=5.0 and the overall judgment.
  • §1.D / UI surfaces — no new visual surface beyond a TBD toast string; the absent refetch-failure UI state is the main FMC/UI-State deduction.
  • §4.C/§4.D — concrete chunked plan + numbered rollback; raised TPS/ROL.