@saluzi/saluzi-edu 0.2.78 → 0.2.80

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saluzi/saluzi-edu",
3
- "version": "0.2.78",
3
+ "version": "0.2.80",
4
4
  "description": "Saluzi CLI - interactive AI coding assistant in the terminal",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -357,6 +357,51 @@ describe('artifacts routes', () => {
357
357
  expect(row?.session_id).toBeNull()
358
358
  })
359
359
 
360
+ test('v1 upload with session_id is visible to the session owner in the web gallery', async () => {
361
+ // The CLI artifact tool's contract (spawn-mode children send their
362
+ // --session-id argv value): a worker-authenticated upload attributed to
363
+ // a session must appear for that session's owner — in the session view
364
+ // AND the owner's default gallery scope. Without session attribution the
365
+ // row is creator-less and invisible to everyone except admins.
366
+ const session = storeCreateSession({ title: 'ai gen session' })
367
+ storeBindSession(session.id, user.id)
368
+
369
+ const res = await app.request('/v1/artifacts', {
370
+ method: 'POST',
371
+ headers: { ...AUTH_HEADERS, 'Content-Type': 'application/json' },
372
+ body: JSON.stringify({
373
+ html: '<p>dashboard</p>',
374
+ session_id: session.id,
375
+ title: 'AI Dashboard',
376
+ }),
377
+ })
378
+ expect(res.status).toBe(201)
379
+ const data = (await res.json()) as { id: string }
380
+
381
+ // Session-filtered gallery (embedded panel in session detail).
382
+ const sessionList = await app.request(
383
+ `/web/artifacts?session_id=${session.id}`,
384
+ { headers: { Authorization: issueBearer(user.id) } },
385
+ )
386
+ expect(sessionList.status).toBe(200)
387
+ const sessionRows = (await sessionList.json()) as Array<{ id: string }>
388
+ expect(sessionRows.map(r => r.id)).toContain(data.id)
389
+
390
+ // Owner's default gallery scope (standalone gallery, no team context).
391
+ const defaultList = await app.request('/web/artifacts', {
392
+ headers: { Authorization: issueBearer(user.id) },
393
+ })
394
+ const defaultRows = (await defaultList.json()) as Array<{ id: string }>
395
+ expect(defaultRows.map(r => r.id)).toContain(data.id)
396
+
397
+ // Strangers still see nothing (session is private to the owner).
398
+ const strangerList = await app.request('/web/artifacts', {
399
+ headers: { Authorization: issueBearer(stranger.id) },
400
+ })
401
+ const strangerRows = (await strangerList.json()) as Array<{ id: string }>
402
+ expect(strangerRows.map(r => r.id)).not.toContain(data.id)
403
+ })
404
+
360
405
  test('GET /web/artifacts requires auth', async () => {
361
406
  const res = await app.request('/web/artifacts')
362
407
  expect(res.status).toBe(401)