Changeset 0.28.3 (#187)

This commit is contained in:
2026-03-14 12:30:57 +00:00
parent b2c03be001
commit f68a58b073
46 changed files with 1589 additions and 107 deletions

View File

@@ -1,5 +1,306 @@
# Changelog
## [0.28.3] — 2026-03-13
### Summary
ICD audit close-out and straggler sweep. Rolls in the remaining v0.28.2
items (websocket doc, auth/enums reconciliation) since the 0.28.3 branch
was cut before the final v0.28.2 changeset landed.
### Changed
#### WebSocket ICD (`websocket.md`) — Full Rewrite
- Event envelope field corrected: `"event"` not `"type"` (matches Go
struct json tag `json:"event"`).
- Room subscribe/unsubscribe documented as **planned, not implemented**.
`JoinRoom`/`LeaveRoom` exist as stubs but no client wiring exists;
all delivery uses `Hub.SendToUser()`.
- Added payload shape documentation for 11 event types:
`message.created` (user + assistant variants), `typing.start`,
`typing.stop`, `typing.user`, `user.presence`, `user.mentioned`,
`notification.new`, `notification.read`, `workflow.assigned`,
`workflow.claimed`, `workflow.advanced`, `workflow.completed`,
`role.fallback`, `tool.call.*`.
- Routing table rewritten with accurate Direction, Delivery mechanism,
and labels matching `events.routeTable` in code.
- Noted that `workflow.claimed`, `workflow.advanced`, `workflow.completed`
use room-scoped `Bus.Publish()` which does not reach WebSocket clients
(rooms not wired). Forward-looking plumbing only.
#### Auth ICD (`auth.md`)
- Login/Register response shape corrected: added `token_type` ("Bearer")
and `expires_in` (900), removed phantom fields (`avatar_url`,
`created_at`, `last_login`) that `generateTokens` does not emit.
- Register documents the admin-approval path (201 with message when
`is_active` is false).
#### Enums ICD (`enums.md`)
- Task run statuses: added missing `queued` status (present in DB CHECK
constraint, was omitted from enum doc).
#### Presence Status Reconciliation
- DB CHECK constraint: `online`, `away`, `offline`.
- Runtime behavior: hub emits only `online` and `offline`. `away` is
reserved for future idle detection.
- Documented this gap in both `websocket.md` and `enums.md` rather than
adding dead code or removing the DB constraint.
#### Housekeeping
- `VERSION` bumped to 0.28.3.
- `CHANGELOG.md` updated with entries for 0.28.0 through 0.28.3.
- `ROADMAP.md` updated: v0.28.2 marked complete, v0.28.3 scope adjusted.
### ICD Runner
No runner changes — websocket events are not testable via HTTP. All
existing tests remain at 469/469 (100%).
### Fixed
#### WebSocket Workflow Event Delivery (cs1)
- `workflow.advanced`, `workflow.completed`, `workflow.claimed` were
emitted via room-scoped `Bus.Publish()`, but the room subscription
system is not wired (no client-side subscribe/unsubscribe). These
events **never reached WebSocket clients**.
- Converted all three to `SendToUser()` per channel participant,
matching the pattern used by `message.created` and
`workflow.assigned`.
- `workflow.claimed` payload gains `channel_id` field (needed to look
up participants; also useful for frontend navigation).
- `workflow_assignments.go`: consolidated the duplicate
`channel_id` query (was queried separately for WS and notification).
### Added
#### JS Dependency Audit (cs2)
- `docs/JS-DEPENDENCY-AUDIT.md`: full map of the frontend codebase.
47 files, 25K lines, 431 top-level globals, 143 dynamic onclick
handlers. Documents the complete script load order per surface,
core global dependency graph (`App` → 20 files, `API` → 36 files,
`UI` → 32 files, `Events` → 9 files), IIFE vs bare global
classification, inline handler inventory, cross-file call graph,
and a 4-phase decomposition strategy (core extract → onclick
migration → ES modules → template handler shim).
#### Core Four IIFE Extraction (cs3)
- `api.js`: Wrapped in IIFE. `BASE` and `_storageKey` are now private
(were leaking as implicit globals). Single export: `window.API`.
- `events.js`: Wrapped in IIFE. Replaced `_storageKey` localStorage
coupling with `API.accessToken` (eliminates cross-file private
dependency). Single export: `window.Events`.
- `app-state.js`: Wrapped in IIFE. `resolveCapabilities()` now private.
Exports: `window.App`, `window.fetchModels`.
- `ui-primitives.js`: Wrapped in IIFE. `updateTabArrows()` now private
(zero external callers). 17 explicit `window.*` exports with manifest
comment. Previously all 18 declarations leaked as implicit globals.
#### Tier 2 IIFE Extraction (cs4)
- `ui-format.js`: Wrapped in IIFE. 11 explicit exports (7 cross-file +
4 onclick handlers), 9 privatized (`_highlightMentions`, `_formatMarked`,
`_formatBasic`, `_unwrapMarkdownFence`, `_decodeHTML`, `_looksLikeHTML`,
`_hasPreviewContent`, `_extractLastHTMLBlock`, `_livePreviewTimer`).
- `ui-core.js`: Wrapped in IIFE. 3 exports (`UI`, `renderPersonaForm`,
`toggleSummarizedHistory`), 3 privatized (`avatarHTML`,
`assistantAvatarURI`, `_isSummaryMessage`).
- `pages.js`: Wrapped in IIFE. 2 exports (`Pages`, `_val`), 6 privatized
(`_pageData`, `_show`, `_hide`, `_toast`, `_parseJSON`, `_api`).
#### Tier 3 IIFE Extraction — Leaf Modules (cs5)
- 11 files wrapped: `channel-models.js`, `chat-pane.js`, `notifications.js`,
`model-selector.js`, `file-tree.js`, `tokens.js`, `code-editor.js`,
`note-editor.js`, `drag-resize.js`, `pane-container.js`, `user-menu.js`.
- 13 total explicit exports across all 11 files.
- 17 functions privatized (e.g. `_shortName`, `_timeAgo`, `_ftFileIcon`,
`_ceFileIcon`, `_ceDetectLanguage`, `dismissContextWarning`, `_clientPos`,
10 PaneContainer internals).
#### Small File IIFE Wrap (cs6)
- 7 files: `admin-surfaces.js`, `extensions.js`, `memory-ui.js`,
`notification-prefs.js`, `persona-kb.js`, `repl.js`, `ui-settings.js`.
- `ui-settings.js` has no standalone exports (extends `UI` via
`Object.assign`); IIFE scopes its closure only.
- 3 functions privatized (`_loadSurfaceList`, `_debounce`,
`savePersonaKBs` — zero external callers).
#### Chat + App Entry Point IIFE Wrap (cs7)
- `chat.js`: Wrapped in IIFE. 22 explicit exports (ChatInput + 21
functions), 7 privatized (`_typingTimer`, `_emitTyping`,
`_saveChatModel`, `_restoreChatModel`, `_cleanStaleChatModel`,
`updateChatTokenCount`, `_autoNamePending`).
- `app.js`: Wrapped in IIFE. 6 exports (`handleLogin`, `handleRegister`,
`handleLogout`, `switchAuthTab`, `startApp`, `initBanners`),
13 privatized. `init()` self-invokes via `DOMContentLoaded` — not
exported. `handleLogout` overrides the base.html fallback on chat,
editor, and notes surfaces.
#### Clean Tier 4 Wraps (cs8)
- `settings-handlers.js`: Wrapped in IIFE. 11 explicit exports + 4
self-assigned `window.*` functions (preserved from original). 13
privatized.
- `note-graph.js`: Wrapped in IIFE. 6 exports, 17 privatized.
- `debug.js`: Wrapped in IIFE. 8 exports (all onclick-referenced from
base.html template), 1 privatized.
- `panels.js`: Wrapped in IIFE. 6 exports, 4 privatized.
#### Heavy Page IIFE Wraps — All Remaining (cs9)
- `files.js`: 18 exports (15 cross-file + 3 onclick), 18 privatized.
- `admin-handlers.js`: 30 exports (28 cross-file + 2 onclick), 10
privatized. Previously misclassified as IIFE — was actually bare
globals.
- `notes.js`: 12 exports (9 cross-file + 3 onclick), 31 privatized.
- `ui-admin.js`: 3 exports (`ADMIN_SECTIONS`, `ADMIN_LABELS`,
`ADMIN_LOADERS`), 1 privatized. Also extends `UI` via
`Object.assign` (28 onclick handlers are UI methods, not standalone).
- `projects-ui.js`: 48 exports (29 cross-file + 19 onclick), 30
privatized. Largest file in the codebase (78 top-level globals
reduced to 48 explicit exports).
**Frontend decomposition Phase 1 complete.** All 47 JS files are now
IIFE-wrapped with explicit `window.*` exports. Zero implicit globals
remain. The `_storageKey` cross-file coupling between `api.js` and
`events.js` is eliminated. ~168 functions privatized across the
codebase.
## [0.28.2] — 2026-03-13
### Summary
Full ICD audit across all remaining domains. Every ICD document traced
against Go handlers, stores (PG + SQLite), and the ICD test runner.
Eight changesets (cs0cs7), 469/469 runner tests passing.
### Added
#### Go Integration Tests
- `projects_test.go`: 14 tests — CRUD shapes, 201 status, envelope,
admin list, auth, isolation.
- `workspace_test.go`: 11 tests — list empty/data envelope, shape,
root_path not exposed, user isolation, GET by ID, 404, 403, git
credentials empty envelope, auth required.
- `profile_test.go`: GET profile shape, PUT profile, duplicate email
409, settings envelope, password change (success, wrong current 401,
too short 400), avatar delete.
- Knowledge tests: document status polling, document delete, update
empty body 400, permission denial.
#### ICD Runner Tests (v0.28.2.4)
- Projects: rewritten from 9 → 19 tests (full CRUD shapes,
channel/KB/note association lifecycles, files shape, isolation,
admin list).
- Knowledge: document status, document delete, permission, team-scoped
KB creation.
- Profile: all 7 endpoints exercised.
- Workspaces: envelope, shape, isolation, git operations.
- Notifications: envelope, preferences, type enum.
### Fixed
#### P0 — Security
- `SetDiscoverable` on knowledge bases had no authorization check.
Added `loadAndAuthorize` + owner/admin gate + audit log (cs2).
#### P0 — Response Shape
- `GET /settings` returned bare object → wrapped in
`{"settings": {...}}` (cs5).
- `GET /workspaces` returned bare array → `{"data": [...]}` (cs6).
- `GET /git-credentials` returned bare array → `{"data": [...]}` (cs6).
- `GET .../git/log` returned bare array → `{"data": [...]}` + nil
slice guard (cs6).
- `ListByProject` files returned `{"files": null}``{"files": []}` (cs7).
- `GET /notifications/preferences` missing `"preferences"` key in
envelope (cs0).
#### P0 — Data Integrity
- `ListTeamProviderModels` response struct missing `Type` field —
embedding models indistinguishable from chat models, causing Venice
400 on completion (cs7).
#### Notification System
- Implemented `memory.extracted` notification (was missing hook in
memory extractor) (cs0).
- Implemented `user.mentioned` persisted notification (was WS-only) (cs0).
- Implemented `workflow.claimed` persisted notification (was WS-only) (cs0).
- Removed dead `NotifTypeProjectInvite` constant (cs0).
#### ICD Runner (v0.28.2.4)
- SSE parser: extract content from OpenAI-format
`choices[0].delta.content` — was checking top-level `evt.content`.
All three provider tiers (global, team, BYOK) were affected (cs7).
- `pickCheapestChat` excludes embedding/image models by type and ID
pattern (cs7).
- Model ID references use `(m.model_id || m.id)` fallback for team
provider models (cs7).
### Changed
#### ICD Documents Corrected
- `notifications.md`: object shape, query params, response envelopes,
WS events. Type enum synced (removed aspirational, added implemented).
- `knowledge.md`: KB object shape (6 field mismatches), search envelope
(`data` not `results`), search result fields, status progression
(`extracting` step), file type support, auth annotations.
- `profile.md`: avatar API (multipart → JSON base64), response shapes
for all 7 endpoints, auth annotations, field table. Added
`last_login_at` to `profileResponse` + dialect-safe time scan.
- `workspaces.md`: workspace object shape (`indexing_enabled`, `git_*`,
`total_bytes` not `storage_bytes`, `owner_type` full enum), file
entry shape, git status/log/commit shapes, archive format, auth
annotations.
- `projects.md`: full rewrite — 6 categories of drift fixed (ghost
fields removed, 6 missing fields added, create/update shapes
corrected, association objects documented, `omitempty` on computed
counts noted).
- `notes.md`: verified clean.
- `memory.md`: verified clean (audited v0.28.0).
#### Dead Code Removal
- `ListGlobal`/`ListForTeam` on KnowledgeBaseStore — interface + PG +
SQLite (cs4).
- `CreateKB` moved team role check from raw `database.DB.QueryRow` to
`stores.Teams.IsTeamAdmin`; removed `database` import (cs4).
- Stale `/avatar` route aliases removed from integration test harness (cs5).
- `ListDiscoverableKBs` normalized to use `toKBResponse()` (cs3).
## [0.28.1] — 2026-03-12
### Summary
Surfaces ICD audit — first domain audit pass. Corrected 6 ICD
discrepancies and hardened the surface install path.
### Fixed
- ICD `surfaces.md` corrected: field name, archive format, response
shape (6 discrepancies).
- Surface ID slug validation + `extractableRelPath` install hardening
(path traversal defense).
### Added
- 19 E2E surface CRUD tests in ICD runner (install, enable/disable,
delete, error paths).
- 22 handler-level tests + 14 store-level tests (PG + SQLite).
### Changed
- CI timeout increased 8m → 12m for PG integration tests.
## [0.28.0] — 2026-03-12
### Summary
Platform polish arc kickoff. Memory ICD audit — first domain to complete
the full trace-and-test cycle.
### Changed
- `memory.md` ICD audited and verified: object shape, scopes
(`user`/`persona`/`persona_user`), statuses
(`active`/`pending_review`/`archived`), all endpoints, admin review,
AI tools, background extraction, memory injection.
- 13/13 ICD runner tests passing.
## [0.27.5] — 2026-03-11
### Summary