Skip to content
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
4f5a7d4
fix(integrations): preserve rapid legitimate edits
tinsever Sep 29, 2026
95478d8
perf(board): load pages incrementally and patch live changes
tinsever Sep 29, 2026
4e846bb
merge: include formatted integration scope fix
tinsever Sep 29, 2026
232b714
merge: include verified integration ownership fixes
tinsever Sep 29, 2026
df37bca
fix(integrations): identify older outbound echoes and stale events
tinsever Sep 29, 2026
dd614c1
fix(board): preserve bounded cache updates across pagination races
tinsever Sep 29, 2026
5af0a82
fix(integrations): confirm historical text echoes with provider state
tinsever Sep 29, 2026
e469f24
merge: preserve compatible destination integration links
tinsever Sep 29, 2026
8c325f1
fix: address verified delivery and concurrency review findings
tinsever Sep 29, 2026
8e77668
fix: address verified delivery and concurrency review findings
tinsever Sep 29, 2026
1b027ab
merge: inherit guarded integration status lookups
tinsever Sep 29, 2026
1e89b83
fix: bound realtime task refreshes and show public board progress
tinsever Sep 29, 2026
1777ae9
fix: merge outbound history under a link row lock
tinsever Sep 29, 2026
95d9006
merge: inherit current position allocation fixes
tinsever Sep 29, 2026
a4a3d2c
fix: preserve concurrent outbound history during inbound edits
tinsever Sep 29, 2026
0c46a5c
Preserve remote board changes during live local mutations
tinsever Sep 30, 2026
dcd5c75
Merge canonical reorder snapshots into incremental boards
tinsever Sep 30, 2026
55d2435
fix(integrations): classify echoes from locked metadata without block…
tinsever Sep 30, 2026
4267b60
merge: propagate virtual bucket reorders through live boards
tinsever Sep 30, 2026
9503882
merge: preserve scoped PR transitions alongside echo history
tinsever Sep 30, 2026
bd12c1f
merge: preserve atomic reorder guards in incremental boards
tinsever Sep 30, 2026
043214f
fix(integrations): repair late writes and retain guarded links
tinsever Sep 30, 2026
25d5a12
fix(board): reconcile page boundaries and remote label edits
tinsever Sep 30, 2026
f5ff90c
fix(board): guard partial list drags and complete live updates
tinsever Sep 30, 2026
8899e63
fix(board): preserve cached views and drain fallback detail events
tinsever Sep 30, 2026
7039659
merge: propagate committed integration notifications into echo handling
tinsever Sep 30, 2026
d97981a
merge: include committed provider updates in incremental boards
tinsever Sep 30, 2026
a84284f
fix(integrations): repair out-of-order provider state responses
tinsever Sep 30, 2026
acd36e3
fix(board): publish atomic column reorders and imported detail updates
tinsever Sep 30, 2026
08e67d2
merge: propagate complete task creation notifications into echo handling
tinsever Sep 30, 2026
4af43fc
merge: propagate complete task creation notifications into live boards
tinsever Sep 30, 2026
84e7a55
fix(integrations): persist pending outbound intents before provider w…
tinsever Sep 30, 2026
bcb8584
fix(board): wait for complete pages before archive-all
tinsever Sep 30, 2026
198b17c
fix(integrations): correlate pending echoes with provider versions
tinsever Sep 30, 2026
17236ef
merge ownership fixes into echo handling
tinsever Sep 30, 2026
52eb2d1
fix(board): preserve labels across fetches and remote renames
tinsever Sep 30, 2026
c7711aa
fix(integrations): preserve timestamp collisions and bound pending we…
tinsever Sep 30, 2026
d96566c
perf(board): bound progress snapshot work during pagination
tinsever Sep 30, 2026
667e442
fix(board): preserve edits during initial pagination
tinsever Sep 30, 2026
7faaa96
fix(integrations): recover deferred edits after writer crashes
tinsever Sep 30, 2026
eb619ef
fix(board): reconcile changing public pagination
tinsever Sep 30, 2026
ed40a77
fix(integrations): preserve newer edits during crash recovery
tinsever Sep 30, 2026
af3409a
fix(integrations): repair using the current local value
tinsever Sep 30, 2026
5c9b8e4
fix(board): reconcile public related pages
tinsever Sep 30, 2026
8cb307e
fix(integrations): stop corrective writes after disconnect
tinsever Sep 30, 2026
719a78b
fix(integrations): confirm colliding reversed deliveries
tinsever Sep 30, 2026
87c8d3d
fix(board): refresh label choices and guard disabled drops
tinsever Sep 30, 2026
d468019
fix(integrations): distinguish first-write crash recovery
tinsever Sep 30, 2026
1a1a0a8
fix(board): refresh moved parents and stabilize page revisions
tinsever Sep 30, 2026
e95ab6b
fix(integrations): retire deferred reads for missing issues
tinsever Sep 30, 2026
1666d4d
fix(integrations): order provider edits and repair uncertain writes
tinsever Sep 30, 2026
ecda605
fix(integrations): guard observed recovery against concurrent edits
tinsever Sep 30, 2026
c2c3bcf
fix(integrations): revalidate provider confirmation snapshots
tinsever Sep 30, 2026
1c51887
docs: update sponsors
github-actions[bot] Sep 30, 2026
a404003
test(integrations): provide a fresh confirmation after metadata changes
tinsever Sep 30, 2026
7ec77a0
fix(integrations): stop sync retries after provider reconfiguration
tinsever Sep 30, 2026
16ba4fa
fix(integrations): bound and coalesce corrective provider writes
tinsever Sep 30, 2026
b1857c6
fix(integrations): retire uncertain intents after queued corrections
tinsever Sep 30, 2026
75c47ad
fix(integrations): retire all captured uncertain writes after repair
tinsever Sep 30, 2026
5a2f16f
fix(integrations): revalidate inbound confirmation repository scope
tinsever Sep 30, 2026
0a25118
test(integrations): seed a valid provider repository binding
tinsever Sep 30, 2026
f6c1f39
fix(integrations): persist each successful field repair before contin…
tinsever Sep 30, 2026
b32b357
fix(integrations): settle concurrent uncertainty at correction receipts
tinsever Sep 30, 2026
3728f7c
fix(integrations): index deferred jobs and claim replay across replicas
tinsever Sep 30, 2026
14d1869
fix(integrations): preserve queued field intent ordering
tinsever Sep 30, 2026
b085cb1
fix(integrations): retire intents from obsolete provider bindings
tinsever Sep 30, 2026
4e674b8
Merge PR #1878 into dependent PR #1879
tinsever Sep 30, 2026
0f47144
fix(integrations): preserve webhook versions and final workflow states
tinsever Sep 30, 2026
ca79249
Merge pull request #1867 from usekaneo/fix/review-06-integration-scope
tinsever Sep 30, 2026
1d546b7
Merge pull request #1874 from usekaneo/fix/review-16-integration-echoes
tinsever Sep 30, 2026
a143c88
Merge main into board stack
tinsever Sep 30, 2026
6068860
fix(board): reconcile status repairs and public page edits
tinsever Sep 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/publish-mcp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ concurrency:

jobs:
publish:
runs-on: blacksmith-4vcpu-ubuntu-2404
# npm provenance and trusted publishing require a GitHub-hosted runner.
runs-on: ubuntu-24.04
if: ${{ github.event_name == 'push' || startsWith(github.event.release.tag_name, 'mcp-v') }}
permissions:
# gh release create needs contents: write; npm publish --provenance needs id-token: write.
Expand All @@ -27,7 +28,7 @@ jobs:

steps:
- name: Checkout repository
uses: useblacksmith/checkout@25227e61ff9dafe400e22fa487b673eac4e4409a # v1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
fetch-depth: 0
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/publish-planka-import.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ concurrency:

jobs:
publish:
runs-on: blacksmith-4vcpu-ubuntu-2404
# npm provenance and trusted publishing require a GitHub-hosted runner.
runs-on: ubuntu-24.04
if: ${{ github.event_name == 'push' || startsWith(github.event.release.tag_name, 'planka-import-v') }}

steps:
- name: Checkout repository
uses: useblacksmith/checkout@25227e61ff9dafe400e22fa487b673eac4e4409a # v1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
fetch-depth: 0
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Treat this guide as a set of defaults. The developer's request takes precedence.
## What matters

- Keep routine work simple. Solve the user's problem with the smallest model that makes the behavior clear. Read the relevant code first, but do not keep complexity just because it is already there.
- Keep modules small. Across the whole repo, give each file one responsibility: one component per file, and pure helpers and types in their own modules next to the code that uses them, with tests beside them. When a file grows a second concern, split it into a folder. Do not extract one-line wrappers; inline those.
- Keep boards fast. Task-heavy views and realtime updates should not move or render more data than they need.
- Keep self-hosting easy. A single instance must work without Redis or another managed service. Support both bundled same-origin and separately hosted API and web deployments.
- Respect workspace boundaries. The API enforces authentication and permissions; a hidden UI control is not an authorization check. Never leak secrets or private workspace data through responses, logs, events, WebSockets, or MCP.
Expand Down
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
### Features

- clickable task PR list, task link matching, and reopen completed tasks for new work: #1864
- **mcp:** get tasks by ticket ID: #1839

### Bug Fixes

- **ci:** publish npm provenance on GitHub-hosted runners: [50779a4](https://github.com/usekaneo/kaneo/commit/50779a4e21159ad322dc4dd18fa7f1689bee64fa)
- **ci:** pass the GitHub token to AgentScan: #1862
- **ci:** resolve nightly warnings and errors: #1858
- **api:** make legacy MCP HTTP requests replica independent: #1850
- **docker:** disable wget proxy for loopback health checks: #1841

### Documentation

- add AI Policy badge to README: [011c8ee](https://github.com/usekaneo/kaneo/commit/011c8ee731cc684644d8bf568f4a5f74e194878c)
- update sponsors: [e45c8ac](https://github.com/usekaneo/kaneo/commit/e45c8aceed5da9bcc040a592be9677c79133aecd)

### Credits

Huge thanks to @andrejsshell, @tinsever, @randoneering, and @mazzz1y for helping!

### Features

- **web:** guide cloud users through invites and plan choice during onboarding: #1840
- rank new issue priority with Jev: [594e016](https://github.com/usekaneo/kaneo/commit/594e0168dbf586b09d1b0a946e5da9148485b76c)

Expand Down
3 changes: 3 additions & 0 deletions apps/api/src/column/controllers/create-column.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { publishEvent } from "../../events";
import { eq, sql } from "drizzle-orm";
import { HTTPException } from "hono/http-exception";
import db from "../../database";
Expand Down Expand Up @@ -81,6 +82,8 @@ async function createColumn({
throw new HTTPException(500, { message: "Failed to create column" });
}

await publishEvent("project.updated", { projectId: created.projectId });

return created;
}

Expand Down
3 changes: 3 additions & 0 deletions apps/api/src/column/controllers/delete-column.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { publishEvent } from "../../events";
import { eq, sql } from "drizzle-orm";
import { HTTPException } from "hono/http-exception";
import db from "../../database";
Expand Down Expand Up @@ -26,6 +27,8 @@ async function deleteColumn(id: string) {

await db.delete(columnTable).where(eq(columnTable.id, id));

await publishEvent("project.updated", { projectId: existing.projectId });

return existing;
}

Expand Down
39 changes: 23 additions & 16 deletions apps/api/src/column/controllers/reorder-columns.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { publishEvent } from "../../events";
import { and, eq } from "drizzle-orm";
import { HTTPException } from "hono/http-exception";
import db from "../../database";
Expand All @@ -7,27 +8,33 @@ async function reorderColumns(
projectId: string,
columns: Array<{ id: string; position: number }>,
) {
for (const col of columns) {
const [updated] = await db
.update(columnTable)
.set({ position: col.position })
.where(
and(eq(columnTable.id, col.id), eq(columnTable.projectId, projectId)),
)
.returning({ id: columnTable.id });
const updated = await db.transaction(async (tx) => {
for (const col of [...columns].sort((left, right) =>
left.id.localeCompare(right.id),
)) {
const [updated] = await tx
.update(columnTable)
.set({ position: col.position })
.where(
and(eq(columnTable.id, col.id), eq(columnTable.projectId, projectId)),
)
.returning({ id: columnTable.id });

if (!updated) {
throw new HTTPException(400, {
message: `Column ${col.id} does not belong to this project`,
});
if (!updated) {
throw new HTTPException(400, {
message: `Column ${col.id} does not belong to this project`,
});
}
}
}

const updated = await db.query.columnTable.findMany({
where: eq(columnTable.projectId, projectId),
orderBy: (columns, { asc }) => [asc(columns.position)],
return tx.query.columnTable.findMany({
where: eq(columnTable.projectId, projectId),
orderBy: (columns, { asc }) => [asc(columns.position)],
});
});

await publishEvent("project.updated", { projectId });

return updated;
}

Expand Down
2 changes: 2 additions & 0 deletions apps/api/src/column/controllers/update-column.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ async function updateColumn(
});
}

await publishEvent("project.updated", { projectId: updated.projectId });

return updated;
}

Expand Down
Loading