WS-7 PR-3 commit 1. Frontend mirror of the backend SDK install (commits bdb89a2..adab3be), wired against the existing apps/app SPA. - pnpm add @sentry/vue@10.52.0 (pinned). - src/observability/sentry.ts: initSentry() — empty DSN no-op (RFC §3.3), errors-only (tracesSampleRate=0, profilesSampleRate=0; RFC §2 amend.B), sendDefaultPii=false, Console integration off, beforeSend wired to the scrubber, initial scope tag app=app for GlitchTip filtering. - src/observability/scrubber.ts: TypeScript port of backend SentryEventScrubber. RFC §3.7 frontend block — body / header / query scrubbing, form_values wholesale replacement, cookies wholesale, defensive strip of contexts.storage and user.cookies, max-depth guard. - src/observability/contextBinding.ts: Vue Router beforeEach guard that binds RFC §3.6 auth-scope tags per navigation. Three zones via route.meta.public + route.path matching: - portal token zone (meta.public + meta.context=portal) → actor_scope= portal, no user_id (RFC §3.6 explicit) - /platform/* with super_admin → actor_scope=platform, no org tag - default authenticated → actor_scope=organisation when an active organisation is selected (useOrganisationStore.activeOrganisationId), otherwise actor_scope=user - unauthenticated public pages → actor_scope=anonymous Reads useAuthStore (user, appRoles, isSuperAdmin) and useOrganisationStore (activeOrganisationId) — corrected vs. RFC's speculative auth-store API. - src/observability/index.ts: barrel. - src/main.ts: initSentry runs before registerPlugins so Sentry's Vue errorHandler hooks before any plugin or component initialises; installContextBinding runs after registerPlugins so pinia is up. - env.d.ts: VITE_SENTRY_DSN_FRONTEND + VITE_SENTRY_RELEASE typed. - .env.example: new file (didn't exist before) documenting all SPA env vars including the new Sentry pair. - vite.config.ts: build.sourcemap=true (RFC §3.5 — generated, uploaded to GlitchTip by deploy.sh, then stripped before nginx serves dist/). Typecheck: green. Build: green, *.map files emitted alongside *.js chunks as expected. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
39 lines
1.2 KiB
TypeScript
39 lines
1.2 KiB
TypeScript
import { createApp } from 'vue'
|
|
import { VueQueryPlugin } from '@tanstack/vue-query'
|
|
import { queryClientConfig } from '@/lib/query-client'
|
|
import { initSentry, installContextBinding } from '@/observability'
|
|
import { router } from '@/plugins/1.router'
|
|
|
|
import App from '@/App.vue'
|
|
import { registerPlugins } from '@core/utils/plugins'
|
|
|
|
// Styles
|
|
import '@core/scss/template/index.scss'
|
|
import '@styles/styles.scss'
|
|
|
|
// Create vue app
|
|
const app = createApp(App)
|
|
|
|
// RFC-WS-7 — Sentry init runs before plugin registration so the SDK can
|
|
// hook Vue's errorHandler before any plugin or component initialises.
|
|
// Empty DSN = SDK no-op (mirrors backend behaviour, RFC §3.3).
|
|
initSentry({
|
|
app,
|
|
router,
|
|
dsn: import.meta.env.VITE_SENTRY_DSN_FRONTEND ?? '',
|
|
release: import.meta.env.VITE_SENTRY_RELEASE ?? '',
|
|
environment: import.meta.env.MODE,
|
|
})
|
|
|
|
// Register plugins (router, pinia, vuetify, …).
|
|
registerPlugins(app)
|
|
|
|
// Bind auth-scope tags per route navigation. Must run after pinia is set
|
|
// up by registerPlugins (the guard reads useAuthStore / useOrganisationStore).
|
|
installContextBinding(router)
|
|
|
|
app.use(VueQueryPlugin, queryClientConfig)
|
|
|
|
// Mount vue app
|
|
app.mount('#app')
|