Feat v0.5.2 chat surface

Chat surface package (packages/chat/) with conversation list, message
thread, compose bar, participant sidebar, create conversation dialog,
typing indicators, read receipts, message editing, and message deletion.
Built on chat-core library with realtime event subscriptions.

Fix stale token login deadlock: REST client auth endpoints excluded
from 401 retry loop, 8s defensive boot timeout on auth.boot().

Fix bundled package permissions: auto-grant with NULL granted_by and
set status active on install.

Switch docker-compose to named volume for remote Docker host compat.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-30 14:48:18 +00:00
parent 7155aaf663
commit a0cd724d35
12 changed files with 1476 additions and 20 deletions

View File

@@ -11,6 +11,7 @@ import (
"os"
"path/filepath"
"strings"
"time"
"github.com/gin-gonic/gin"
@@ -191,7 +192,21 @@ func installBundledPackage(pkgPath, packagesDir string, stores store.Stores, run
// Sync permissions — use a minimal gin.Context for the functions that need it
fakeCtx := newBackgroundGinContext()
SyncManifestPermissions(fakeCtx, stores, pkgID, manifest)
declaredPerms := SyncManifestPermissions(fakeCtx, stores, pkgID, manifest)
// Bundled packages are trusted — auto-grant all declared permissions
// and restore active status (SyncManifestPermissions sets pending_review).
// Use direct SQL with NULL granted_by to satisfy FK constraint on users(id).
if len(declaredPerms) > 0 {
now := time.Now().UTC().Format(time.RFC3339)
_, err := database.DB.ExecContext(ctx,
`UPDATE extension_permissions SET granted = 1, granted_by = NULL, granted_at = ? WHERE package_id = ? AND granted = 0`,
now, pkgID)
if err != nil {
log.Printf("[bundled] Failed to auto-grant permissions for %s: %v", pkgID, err)
}
_ = stores.Packages.SetStatus(ctx, pkgID, "active")
}
// Sync triggers from manifest
SyncManifestTriggers(ctx, stores, triggers.GlobalEngine(), pkgID, manifest)