LLasitava Projects
BUILD / BUILD-21

Webhook/event push: board changes visible as they happen

P1 feature In Review
Description
JC 2026-08-23: move to webhook model so board changes are seen live. Design: activity is already written per event (item.created/item.transitioned/comment.added) — add DDB Stream on the table -> dispatcher Lambda -> outbound webhook targets (subscription registry, tenant-style config). Phase A (cheap, immediate): Slack push to #noskana-dev via existing secret noskana/prod/slack/dev-webhook — event type, item key, title, actor, substance (comment preview / from->to), deep link to /app/p/BUILD/items/{key}. Phase B: web UI live updates — start with polling island (fits P6.3 islands work), upgrade to SSE/WebSocket later (API GW WebSocket = NEW resource type, needs JC allowlist consent per standing rule). Phase C: generic subscriber registry (per-project webhook URLs) as part of BUILD-8 capture platform. All zip-Lambda FaaS, no Docker.
Labels
capture webhooks web
Comments
agent:claude-peagent2026-08-23T18:08:51.061Z
**Phase B LIVE** (dbdafab, batch d6db410) - Board + table poll every 15s (same-origin passthrough, key server-side), pause on hidden tab, instant refetch on focus - Drag-guard: polls never clobber an in-flight optimistic move - Gold live-dot affordance; reduced-motion respected - Item detail stays SSR-static this phase; Phase C rides BUILD-8
agent:build-agentagent2026-08-23T18:01:55.295Z
**Phase B — board/table auto-update: implemented, gates green** - Board (KanbanBoard) + Table (TableView) islands now poll every 15s, same-origin, via new public GET passthroughs `/app/api/projects/{projectKey}/board` and `/app/api/projects/{projectKey}/items` (mirrors the existing `transition.ts` self-hop pattern — no WEB_API_KEY exposed client-side). - No infra change needed: `GET /app/{proxy+}` is already a public route (route-sweep invariant confirmed), so the new read routes are covered by the existing allowlist. - Polling pauses on `document.hidden`, refetches immediately on window `focus`, shared via a new `usePolling` hook (`web/src/lib/live/usePolling.ts`). - Drag-guard: KanbanBoard holds a polled board update in a pending ref while a drag or settle animation is in flight, applying it the instant both clear — never clobbers an in-flight optimistic move. - Subtle gold pulse-dot "Live" affordance (`LiveIndicator.tsx`), shared by both islands, respects `prefers-reduced-motion` (static dim dot instead of the pulse loop). - Item detail page stays SSR-only/static this phase (no island exists there yet) — out of scope per brief. - Gates: web vitest 257/257 green, coverage ratchet 100% held; `pnpm run typecheck` clean; `npx astro check` clean; `check-astro-ssr-bundle.sh` OK. - TDD: every new file (usePolling, liveClient, LiveIndicator, board/items routes, KanbanBoard/TableView polling behavior) written red-first.
agent:claude-peagent2026-08-23T16:20:21.332Z
Phase A LIVE-VERIFIED: dispatcher Lambda invoked on both probes (this comment + the In Review transition), ESM LastProcessingResult=OK, zero error logs (Slack POST failures would console.error) => messages delivered to #noskana-dev. Item stays In Review pending JC eyeball of the channel; Phases B/C tracked as subtasks.
agent:claude-peagent2026-08-23T16:17:28.274Z
Phase A merged (98d54e7) + deployed. This very comment is the live-verify probe: it should arrive in #noskana-dev via the DDB stream -> slackDispatcherFn.
agent:build-agentagent2026-08-23T16:13:14.782Z
FINISHED BUILD-21 Phase A. Branch feat/board-slack-webhook pushed, sha 98d54e7 (rebased on 1ec834f main). Delivered: NEW_IMAGE stream on lasitava-projects table; slackDispatcherFn (NodejsFunction zip) consuming stream via DynamoEventSource (reportBatchItemFailures + bisectBatchOnError + retryAttempts 3, LATEST, batch 10); filters to Activity rows (SK ACT# prefix), formats event type + item key/title + actor + substance (comment 200-char preview / transition from->to / created type+priority / metric agent+tok+ms) + deep link /app/p/{projectKey}/items/{itemKey}; webhook from Secrets Manager noskana/prod/slack/dev-webhook (grantRead, cached per container). No new HTTP surface. Gates: TDD failing-first, 52 new tests green, 100/100/100/100 coverage on all new src files (ratchet holds), tsc --noEmit clean, projects-stack.test.ts 57/57 green standalone (count assertions updated 13->14 Lambda / 10->11 IAM + 5 new BUILD-21 synth assertions), cdk synth LasitavaProjectsStack succeeded (SlackDispatcherFn bundled 9.4kb). Known pre-existing red NOT mine: pipeline-stack.test.ts npm-ci assertion (fix on fix/pipeline-stack-test-pnpm). Not deployed (controller does).
agent:build-agentagent2026-08-23T15:34:33.562Z
Starting BUILD-21 Phase A: live Slack push of board activity. Plan: enable DDB Stream (NEW_IMAGE) on projects table, new dispatcher NodejsFunction Lambda consuming stream, filtering to activity records, formatting Slack messages (event type, item key/title, actor, substance, deep link), posting to noskana/prod/slack/dev-webhook secret. TDD: failing tests first for format/filter/failure paths. Branch feat/board-slack-webhook off origin/main. No deploy.
agent:claude-peagent2026-08-23T15:33:46.043Z
QUEUE #1 — pulled to front of To Do (visibility want is NOW; also multiplies value of every later item). Phase A (Slack push) is small: DDB Stream + one dispatcher Lambda + existing Slack secret. Dispatch as soon as a build team frees up; BUILD-8 absorbs Phase C.
Activity
agent:claude-peagent comment.added
2026-08-23T18:08:51.072Z
agent:build-agentagent comment.added
2026-08-23T18:01:56.199Z
agent:claude-peagent comment.added
2026-08-23T16:20:21.374Z
agent:claude-peagent subtask.created
2026-08-23T16:20:21.140Z
agent:claude-peagent subtask.created
2026-08-23T16:20:20.880Z
agent:claude-peagent subtask.created
2026-08-23T16:20:20.561Z
agent:claude-peagent item.transitioned
2026-08-23T16:19:36.303Z
agent:claude-peagent comment.added
2026-08-23T16:17:28.555Z
agent:build-agentagent comment.added
2026-08-23T16:13:15.673Z
agent:build-agentagent comment.added
2026-08-23T15:34:33.603Z
agent:claude-peagent comment.added
2026-08-23T15:33:46.103Z
agent:claude-peagent item.transitioned
2026-08-23T15:33:45.608Z
agent:claude-peagent item.created
2026-08-23T15:33:30.688Z