@prmichaelsen/acp-visualizer 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/package.json +8 -10
  2. package/src/components/ExtraFieldsBadge.tsx +1 -1
  3. package/src/components/FilterBar.tsx +1 -1
  4. package/src/components/Header.tsx +1 -1
  5. package/src/components/MilestoneTable.tsx +1 -1
  6. package/src/components/MilestoneTree.tsx +2 -2
  7. package/src/components/StatusBadge.tsx +1 -1
  8. package/src/components/StatusDot.tsx +1 -1
  9. package/src/components/TaskList.tsx +1 -1
  10. package/src/routes/__root.tsx +5 -5
  11. package/src/routes/api/watch.ts +1 -1
  12. package/src/routes/index.tsx +2 -2
  13. package/src/routes/milestones.tsx +7 -7
  14. package/src/routes/search.tsx +4 -4
  15. package/src/routes/tasks.tsx +3 -3
  16. package/src/services/progress-database.service.ts +3 -3
  17. package/agent/commands/acp.clarification-address.md +0 -417
  18. package/agent/commands/acp.clarification-capture.md +0 -386
  19. package/agent/commands/acp.clarification-create.md +0 -437
  20. package/agent/commands/acp.clarifications-research.md +0 -326
  21. package/agent/commands/acp.command-create.md +0 -432
  22. package/agent/commands/acp.design-create.md +0 -286
  23. package/agent/commands/acp.design-reference.md +0 -355
  24. package/agent/commands/acp.handoff.md +0 -270
  25. package/agent/commands/acp.index.md +0 -423
  26. package/agent/commands/acp.init.md +0 -546
  27. package/agent/commands/acp.package-create.md +0 -895
  28. package/agent/commands/acp.package-info.md +0 -212
  29. package/agent/commands/acp.package-install.md +0 -539
  30. package/agent/commands/acp.package-list.md +0 -280
  31. package/agent/commands/acp.package-publish.md +0 -541
  32. package/agent/commands/acp.package-remove.md +0 -293
  33. package/agent/commands/acp.package-search.md +0 -307
  34. package/agent/commands/acp.package-update.md +0 -361
  35. package/agent/commands/acp.package-validate.md +0 -540
  36. package/agent/commands/acp.pattern-create.md +0 -386
  37. package/agent/commands/acp.plan.md +0 -587
  38. package/agent/commands/acp.proceed.md +0 -882
  39. package/agent/commands/acp.project-create.md +0 -675
  40. package/agent/commands/acp.project-info.md +0 -312
  41. package/agent/commands/acp.project-list.md +0 -226
  42. package/agent/commands/acp.project-remove.md +0 -379
  43. package/agent/commands/acp.project-set.md +0 -227
  44. package/agent/commands/acp.project-update.md +0 -307
  45. package/agent/commands/acp.projects-restore.md +0 -228
  46. package/agent/commands/acp.projects-sync.md +0 -347
  47. package/agent/commands/acp.report.md +0 -407
  48. package/agent/commands/acp.resume.md +0 -239
  49. package/agent/commands/acp.sessions.md +0 -301
  50. package/agent/commands/acp.status.md +0 -293
  51. package/agent/commands/acp.sync.md +0 -364
  52. package/agent/commands/acp.task-create.md +0 -500
  53. package/agent/commands/acp.update.md +0 -302
  54. package/agent/commands/acp.validate.md +0 -466
  55. package/agent/commands/acp.version-check-for-updates.md +0 -276
  56. package/agent/commands/acp.version-check.md +0 -191
  57. package/agent/commands/acp.version-update.md +0 -289
  58. package/agent/commands/command.template.md +0 -339
  59. package/agent/commands/git.commit.md +0 -526
  60. package/agent/commands/git.init.md +0 -514
  61. package/agent/commands/tanstack-cloudflare.deploy.md +0 -272
  62. package/agent/commands/tanstack-cloudflare.tail.md +0 -275
  63. package/agent/design/.gitkeep +0 -0
  64. package/agent/design/design.template.md +0 -154
  65. package/agent/design/local.dashboard-layout-routing.md +0 -288
  66. package/agent/design/local.data-model-yaml-parsing.md +0 -310
  67. package/agent/design/local.search-filtering.md +0 -331
  68. package/agent/design/local.server-api-auto-refresh.md +0 -235
  69. package/agent/design/local.table-tree-views.md +0 -299
  70. package/agent/design/local.visualizer-requirements.md +0 -349
  71. package/agent/design/requirements.template.md +0 -387
  72. package/agent/index/.gitkeep +0 -0
  73. package/agent/index/acp.core.yaml +0 -137
  74. package/agent/index/local.main.template.yaml +0 -37
  75. package/agent/manifest.template.yaml +0 -13
  76. package/agent/manifest.yaml +0 -302
  77. package/agent/milestones/.gitkeep +0 -0
  78. package/agent/milestones/milestone-1-project-scaffold-data-pipeline.md +0 -67
  79. package/agent/milestones/milestone-1-{title}.template.md +0 -206
  80. package/agent/milestones/milestone-2-dashboard-views-interaction.md +0 -79
  81. package/agent/package.template.yaml +0 -86
  82. package/agent/patterns/.gitkeep +0 -0
  83. package/agent/patterns/bootstrap.template.md +0 -1237
  84. package/agent/patterns/pattern.template.md +0 -382
  85. package/agent/patterns/tanstack-cloudflare.acl-permissions.md +0 -332
  86. package/agent/patterns/tanstack-cloudflare.action-bar-item.md +0 -416
  87. package/agent/patterns/tanstack-cloudflare.api-route-handlers.md +0 -401
  88. package/agent/patterns/tanstack-cloudflare.auth-session-management.md +0 -387
  89. package/agent/patterns/tanstack-cloudflare.card-and-list.md +0 -271
  90. package/agent/patterns/tanstack-cloudflare.chat-engine.md +0 -353
  91. package/agent/patterns/tanstack-cloudflare.confirmation-tokens.md +0 -346
  92. package/agent/patterns/tanstack-cloudflare.durable-objects-websocket.md +0 -516
  93. package/agent/patterns/tanstack-cloudflare.email-service.md +0 -431
  94. package/agent/patterns/tanstack-cloudflare.expander.md +0 -98
  95. package/agent/patterns/tanstack-cloudflare.fcm-push.md +0 -115
  96. package/agent/patterns/tanstack-cloudflare.firebase-anonymous-sessions.md +0 -441
  97. package/agent/patterns/tanstack-cloudflare.firebase-auth.md +0 -348
  98. package/agent/patterns/tanstack-cloudflare.firebase-firestore.md +0 -550
  99. package/agent/patterns/tanstack-cloudflare.firebase-storage.md +0 -369
  100. package/agent/patterns/tanstack-cloudflare.form-controls.md +0 -145
  101. package/agent/patterns/tanstack-cloudflare.global-search-context.md +0 -93
  102. package/agent/patterns/tanstack-cloudflare.image-carousel.md +0 -126
  103. package/agent/patterns/tanstack-cloudflare.library-services.md +0 -553
  104. package/agent/patterns/tanstack-cloudflare.lightbox.md +0 -169
  105. package/agent/patterns/tanstack-cloudflare.markdown-content.md +0 -115
  106. package/agent/patterns/tanstack-cloudflare.mention-suggestions.md +0 -98
  107. package/agent/patterns/tanstack-cloudflare.modal.md +0 -156
  108. package/agent/patterns/tanstack-cloudflare.nextjs-to-tanstack-routing.md +0 -461
  109. package/agent/patterns/tanstack-cloudflare.notifications-engine.md +0 -151
  110. package/agent/patterns/tanstack-cloudflare.oauth-token-refresh.md +0 -90
  111. package/agent/patterns/tanstack-cloudflare.og-metadata.md +0 -296
  112. package/agent/patterns/tanstack-cloudflare.pagination.md +0 -442
  113. package/agent/patterns/tanstack-cloudflare.pill-input.md +0 -220
  114. package/agent/patterns/tanstack-cloudflare.provider-adapter.md +0 -401
  115. package/agent/patterns/tanstack-cloudflare.rate-limiting.md +0 -323
  116. package/agent/patterns/tanstack-cloudflare.scheduled-tasks.md +0 -338
  117. package/agent/patterns/tanstack-cloudflare.searchable-settings.md +0 -375
  118. package/agent/patterns/tanstack-cloudflare.slide-over.md +0 -129
  119. package/agent/patterns/tanstack-cloudflare.ssr-preload.md +0 -571
  120. package/agent/patterns/tanstack-cloudflare.third-party-api-integration.md +0 -508
  121. package/agent/patterns/tanstack-cloudflare.toast-system.md +0 -142
  122. package/agent/patterns/tanstack-cloudflare.unified-header.md +0 -280
  123. package/agent/patterns/tanstack-cloudflare.user-scoped-collections.md +0 -628
  124. package/agent/patterns/tanstack-cloudflare.websocket-manager.md +0 -237
  125. package/agent/patterns/tanstack-cloudflare.wrangler-configuration.md +0 -358
  126. package/agent/patterns/tanstack-cloudflare.zod-schema-validation.md +0 -336
  127. package/agent/progress.template.yaml +0 -161
  128. package/agent/progress.yaml +0 -145
  129. package/agent/schemas/package.schema.yaml +0 -276
  130. package/agent/scripts/acp.common.sh +0 -1781
  131. package/agent/scripts/acp.install.sh +0 -333
  132. package/agent/scripts/acp.package-create.sh +0 -924
  133. package/agent/scripts/acp.package-info.sh +0 -288
  134. package/agent/scripts/acp.package-install.sh +0 -893
  135. package/agent/scripts/acp.package-list.sh +0 -311
  136. package/agent/scripts/acp.package-publish.sh +0 -420
  137. package/agent/scripts/acp.package-remove.sh +0 -348
  138. package/agent/scripts/acp.package-search.sh +0 -156
  139. package/agent/scripts/acp.package-update.sh +0 -517
  140. package/agent/scripts/acp.package-validate.sh +0 -1018
  141. package/agent/scripts/acp.uninstall.sh +0 -85
  142. package/agent/scripts/acp.version-check-for-updates.sh +0 -98
  143. package/agent/scripts/acp.version-check.sh +0 -47
  144. package/agent/scripts/acp.version-update.sh +0 -176
  145. package/agent/scripts/acp.yaml-parser.sh +0 -985
  146. package/agent/scripts/acp.yaml-validate.sh +0 -205
  147. package/agent/tasks/.gitkeep +0 -0
  148. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-1-initialize-tanstack-start-project.md +0 -210
  149. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-2-implement-data-model-yaml-parser.md +0 -294
  150. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-3-build-server-api-data-loading.md +0 -193
  151. package/agent/tasks/milestone-1-project-scaffold-data-pipeline/task-4-add-auto-refresh-sse.md +0 -262
  152. package/agent/tasks/milestone-2-dashboard-views-interaction/task-10-polish-integration-testing.md +0 -156
  153. package/agent/tasks/milestone-2-dashboard-views-interaction/task-5-build-dashboard-layout-routing.md +0 -178
  154. package/agent/tasks/milestone-2-dashboard-views-interaction/task-6-build-overview-page.md +0 -141
  155. package/agent/tasks/milestone-2-dashboard-views-interaction/task-7-implement-milestone-table-view.md +0 -153
  156. package/agent/tasks/milestone-2-dashboard-views-interaction/task-8-implement-milestone-tree-view.md +0 -174
  157. package/agent/tasks/milestone-2-dashboard-views-interaction/task-9-implement-search-filtering.md +0 -233
  158. package/agent/tasks/task-1-{title}.template.md +0 -244
  159. package/vitest.config.ts +0 -27
@@ -1,348 +0,0 @@
1
- # Firebase Authentication
2
-
3
- **Category**: Code
4
- **Applicable To**: All server-side auth verification, session management, API route protection, and SSR auth checks
5
- **Status**: Stable
6
-
7
- ---
8
-
9
- ## Overview
10
-
11
- This pattern covers how Firebase Admin SDK authentication is used throughout the project: session cookie management, token verification, route guards, SSR auth, and the client-to-server auth handshake. The project uses a dual-layer system: Firebase Client SDK for client-side auth (sign-in/sign-up) and Firebase Admin SDK (`@prmichaelsen/firebase-admin-sdk-v8`) for server-side session management via long-lived session cookies.
12
-
13
- ---
14
-
15
- ## When to Use This Pattern
16
-
17
- **Use this pattern when:**
18
- - Adding a new API route that requires authentication
19
- - Adding a new SSR `beforeLoad` that needs user context
20
- - Building a new server function (`createServerFn`) that accesses user data
21
- - Implementing admin-only routes or features
22
-
23
- **Don't use this pattern when:**
24
- - Working on purely client-side components with no server interaction
25
- - Building public/unauthenticated endpoints (use no auth check)
26
- - Implementing MCP server auth (use `mcp-jwt.ts` JWT tokens instead)
27
-
28
- ---
29
-
30
- ## Core Principles
31
-
32
- 1. **Session Cookies Over ID Tokens**: Server-side auth uses 14-day session cookies, not short-lived ID tokens
33
- 2. **Dual Verification Fallback**: `verifySessionCookie()` first, then `verifyIdToken()` for migration compatibility
34
- 3. **Null on Failure**: Auth functions return `null` on error, never throw — callers decide how to respond
35
- 4. **Always Initialize First**: Call `initFirebaseAdmin()` before any auth operation
36
- 5. **Anonymous Users Are Valid**: Anonymous sessions are real auth sessions — check `isAnonymous` when restricting features
37
-
38
- ---
39
-
40
- ## Implementation
41
-
42
- ### Auth Flow Overview
43
-
44
- ```
45
- Client Server
46
- │ │
47
- ├─ Firebase signIn/signUp ──────► │
48
- │ (gets ID token) │
49
- │ │
50
- ├─ POST /api/auth/login ──────────► │
51
- │ { idToken, turnstileToken? } │
52
- │ ├─ verifyIdToken(idToken)
53
- │ ├─ createSessionCookie(idToken, 14d)
54
- │ ├─ Set-Cookie: session=...
55
- │ ◄──────────────────────────────── │
56
- │ │
57
- ├─ GET /api/some-endpoint ─────────► │
58
- │ Cookie: session=... ├─ getServerSession(request)
59
- │ │ └─ verifySessionCookie(cookie)
60
- │ │ └─ fallback: verifyIdToken(cookie)
61
- │ ◄─── { data } ────────────────── │
62
- ```
63
-
64
- ### Key Functions
65
-
66
- #### `initFirebaseAdmin()` — SDK Initialization
67
-
68
- **File**: `src/lib/firebase-admin.ts`
69
-
70
- ```typescript
71
- import { initializeApp as _initializeApp } from '@prmichaelsen/firebase-admin-sdk-v8'
72
-
73
- export function initFirebaseAdmin() {
74
- _initializeApp({
75
- serviceAccount: process.env.FIREBASE_ADMIN_SERVICE_ACCOUNT_KEY,
76
- projectId: process.env.FIREBASE_PROJECT_ID,
77
- })
78
- }
79
- ```
80
-
81
- Called at the start of every API route handler and SSR `beforeLoad`. Idempotent — safe to call multiple times.
82
-
83
- #### `getServerSession(request)` — Session Verification
84
-
85
- **File**: `src/lib/auth/session.ts`
86
-
87
- ```typescript
88
- import { verifyIdToken, verifySessionCookie } from '@prmichaelsen/firebase-admin-sdk-v8'
89
-
90
- export async function getServerSession(request: Request): Promise<ServerSession | null> {
91
- const sessionCookie = getSessionCookie(request)
92
- if (!sessionCookie) return null
93
-
94
- let decodedToken
95
- try {
96
- decodedToken = await verifySessionCookie(sessionCookie)
97
- } catch {
98
- // Migration fallback — old ID tokens in cookies
99
- decodedToken = await verifyIdToken(sessionCookie)
100
- }
101
-
102
- const isAnonymous = decodedToken.firebase?.sign_in_provider === 'anonymous' || !decodedToken.email
103
-
104
- return {
105
- user: {
106
- uid: decodedToken.sub,
107
- email: decodedToken.email || null,
108
- displayName: decodedToken.name || null,
109
- photoURL: decodedToken.picture || null,
110
- emailVerified: decodedToken.email_verified || false,
111
- isAnonymous,
112
- }
113
- }
114
- }
115
- ```
116
-
117
- #### `getAuthSession()` — TanStack Server Function
118
-
119
- **File**: `src/lib/auth/server-fn.ts`
120
-
121
- ```typescript
122
- export const getAuthSession = createServerFn({ method: 'GET' }).handler(async () => {
123
- initFirebaseAdmin()
124
- const session = await getServerSession(getRequest())
125
- return session?.user || null
126
- })
127
- ```
128
-
129
- Uses `getRequest()` from `@tanstack/react-start/server` to access the Request object.
130
-
131
- #### `createSessionCookie(idToken)` — Cookie Creation
132
-
133
- **File**: `src/lib/auth/session.ts`
134
-
135
- ```typescript
136
- export async function createSessionCookie(idToken: string): Promise<string> {
137
- const sessionCookie = await createFirebaseSessionCookie(idToken, {
138
- expiresIn: 60 * 60 * 24 * 14 * 1000 // 14 days
139
- })
140
- return sessionCookie
141
- }
142
- ```
143
-
144
- #### Route Guards
145
-
146
- **File**: `src/lib/auth/guards.ts`
147
-
148
- ```typescript
149
- export async function requireAuth(request: Request): Promise<Response | null> {
150
- const session = await getServerSession(request)
151
- if (!session?.user) {
152
- return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 })
153
- }
154
- return null // null = authorized
155
- }
156
-
157
- export async function requireAdmin(request: Request): Promise<Response | null> {
158
- const session = await getServerSession(request)
159
- if (!session?.user) return new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401 })
160
-
161
- const ownerEmails = (process.env.OWNER_EMAILS || '').split(',').map(e => e.trim())
162
- if (!session.user.email || !ownerEmails.includes(session.user.email)) {
163
- return new Response(JSON.stringify({ error: 'Forbidden' }), { status: 403 })
164
- }
165
- return null
166
- }
167
- ```
168
-
169
- ---
170
-
171
- ## Examples
172
-
173
- ### Example 1: API Route with Auth
174
-
175
- ```typescript
176
- // src/routes/api/some-endpoint.tsx
177
- GET: async () => {
178
- initFirebaseAdmin()
179
-
180
- const user = await getAuthSession()
181
- if (!user || user.isAnonymous) {
182
- return new Response(JSON.stringify({ error: 'Unauthorized' }), {
183
- status: 401,
184
- headers: { 'Content-Type': 'application/json' },
185
- })
186
- }
187
-
188
- const data = await SomeDatabaseService.getData(user.uid)
189
- return new Response(JSON.stringify({ data }), {
190
- status: 200,
191
- headers: { 'Content-Type': 'application/json' },
192
- })
193
- }
194
- ```
195
-
196
- ### Example 2: SSR beforeLoad with Auth Redirect
197
-
198
- ```typescript
199
- // src/routes/settings/index.tsx
200
- export const Route = createFileRoute('/settings/')({
201
- beforeLoad: (async ({ context }: any) => {
202
- const user = context.initialUser // From root beforeLoad
203
- if (!user || user.isAnonymous) {
204
- throw redirect({
205
- to: '/auth',
206
- search: { redirect_url: '/settings' },
207
- })
208
- }
209
- return { initialUser: user }
210
- }) as any,
211
- component: SettingsPage,
212
- })
213
- ```
214
-
215
- ### Example 3: Server Function with Auth
216
-
217
- ```typescript
218
- const updateProfile = createServerFn({ method: 'POST' })
219
- .inputValidator((data: UpdateProfileInput) => data)
220
- .handler(async ({ data }) => {
221
- initFirebaseAdmin()
222
- const session = await getServerSession(getRequest())
223
- if (!session?.user) throw new Error('Unauthorized')
224
-
225
- return await ProfileDatabaseService.updateProfile(session.user.uid, data)
226
- })
227
- ```
228
-
229
- ### Example 4: Root Route — Global Auth Preloading
230
-
231
- ```typescript
232
- // src/routes/__root.tsx
233
- beforeLoad: async () => {
234
- const user = await getAuthSession()
235
-
236
- let initialAIConsent, initialTosAccepted
237
- if (typeof window === 'undefined' && user && !user.isAnonymous) {
238
- initFirebaseAdmin()
239
- const [consent, tos] = await Promise.all([
240
- ConsentDatabaseService.getAIConsent(user.uid),
241
- TosConsentDatabaseService.hasAcceptedCurrentTos(user.uid),
242
- ])
243
- initialAIConsent = consent?.ai_data_sharing ?? null
244
- initialTosAccepted = tos
245
- }
246
-
247
- return { initialUser: user, initialAIConsent, initialTosAccepted }
248
- }
249
- ```
250
-
251
- ---
252
-
253
- ## Anti-Patterns
254
-
255
- ### Using `getAuthSession()` Where You Have `context.initialUser`
256
-
257
- ```typescript
258
- // Bad: Redundant server function call when root already provides user
259
- beforeLoad: async () => {
260
- const user = await getAuthSession() // Unnecessary extra call
261
- if (!user) throw redirect({ to: '/auth' })
262
- }
263
-
264
- // Good: Use context from root beforeLoad
265
- beforeLoad: async ({ context }: any) => {
266
- const user = context.initialUser // Already fetched by root
267
- if (!user) throw redirect({ to: '/auth' })
268
- }
269
- ```
270
-
271
- ### Throwing on Auth Failure in Session Functions
272
-
273
- ```typescript
274
- // Bad: Throws — callers can't distinguish auth failure from server error
275
- export async function getServerSession(request: Request) {
276
- const cookie = getSessionCookie(request)
277
- if (!cookie) throw new Error('No session') // Don't throw
278
- }
279
-
280
- // Good: Returns null — caller decides the response
281
- export async function getServerSession(request: Request): Promise<ServerSession | null> {
282
- const cookie = getSessionCookie(request)
283
- if (!cookie) return null
284
- }
285
- ```
286
-
287
- ### Forgetting `initFirebaseAdmin()` in API Routes
288
-
289
- ```typescript
290
- // Bad: Will fail on first request
291
- GET: async () => {
292
- const user = await getAuthSession() // Firebase not initialized!
293
- }
294
-
295
- // Good: Always initialize
296
- GET: async () => {
297
- initFirebaseAdmin()
298
- const user = await getAuthSession()
299
- }
300
- ```
301
-
302
- ---
303
-
304
- ## Key Design Decisions
305
-
306
- ### Session Management
307
-
308
- | Decision | Choice | Rationale |
309
- |---|---|---|
310
- | Session mechanism | 14-day session cookie | Longer-lived than ID tokens (1 hour), reduces re-auth |
311
- | Cookie flags | HttpOnly, SameSite=Lax, Secure (prod) | Prevents XSS token theft; Secure disabled on localhost |
312
- | Token fallback | verifySessionCookie → verifyIdToken | Migration compatibility for old ID token cookies |
313
- | Anonymous users | Auto-created on first visit | Enables chat in The Void without signup |
314
-
315
- ### Auth Architecture
316
-
317
- | Decision | Choice | Rationale |
318
- |---|---|---|
319
- | Admin detection | Email match against OWNER_EMAILS env | Simple, no separate admin role system needed |
320
- | MCP auth | Separate JWT system (mcp-jwt.ts) | MCP servers need stateless tokens, not session cookies |
321
- | Rate limiting | 5/min login, 3/5min signup | Prevent brute force and spam signups |
322
- | CAPTCHA | Turnstile for signups, fail-open | Block bots but don't break auth if Turnstile API is down |
323
-
324
- ---
325
-
326
- ## Checklist for Implementation
327
-
328
- - [ ] Call `initFirebaseAdmin()` before any auth operation
329
- - [ ] Use `getAuthSession()` for server functions, `getServerSession(request)` for API routes
330
- - [ ] Check `isAnonymous` when the feature requires a real account
331
- - [ ] Return `null` on auth failure in utility functions (don't throw)
332
- - [ ] Return 401 for unauthenticated, 403 for forbidden in API routes
333
- - [ ] Use `context.initialUser` in `beforeLoad` instead of re-calling `getAuthSession()`
334
- - [ ] Redirect to `/auth?redirect_url=...` for protected pages, not just `/auth`
335
-
336
- ---
337
-
338
- ## Related Patterns
339
-
340
- - **[Database Service Conventions](./database-service-conventions.md)**: Auth-verified userId flows into all database service calls
341
- - **[SSR Preload](./ssr-preload.md)**: SSR `beforeLoad` uses auth context for server-side data fetching
342
-
343
- ---
344
-
345
- **Status**: Stable
346
- **Recommendation**: Follow this pattern for all new API routes, server functions, and SSR routes requiring authentication
347
- **Last Updated**: 2026-03-14
348
- **Contributors**: Community