Commit Graph

59 Commits

Author SHA1 Message Date
Arvin Ansari
b3811c8499
fix(core): Require a project on every activity entry (no-changelog)
`projectId` was nullable, and a null one made the row unreadable: every read
filters on that column, so an unattributed entry was written and then never
surfaced to anyone. The column is now NOT NULL, and `ActivityEventInput`
requires it.

The nullable column existed for one case, and that case turns out to be
fixable. `workflow-deleted` reaches a listener after the workflow row and its
`shared_workflow` rows have cascaded away, so the project cannot be looked up
at that point. But it can be captured before the delete: `workflow.service.ts`
already resolves the workflow, already calls `ownershipService`, and already
runs a `beforeWorkflowDeleted` hook whose stated purpose is capturing rows the
delete is about to cascade away. Enriching the event is upstream work, tracked
on the relay ticket.

Instance-level credentials are not an exception either. `instance_credential_-
assignment` maps a use slot to an ordinary credential that lives in a project;
what is instance-level is the assignment, not the credential.

Two test changes follow. The project-cascade test now writes to two projects
and asserts only the deleted one's entries go, since it can no longer lean on
an unattributed row surviving. And a new test confirms the column rejects an
entry with no project.
2026-09-01 18:35:52 +02:00
Arvin Ansari
55bb7b80d1
docs(core): Correct the user attribution comments on activity entries (no-changelog)
Raised in review: production executions are never linked to a user. They are
already out of the table, and their removal has a consequence the comments still
denied.

Every one of the eleven remaining events carries an acting user. So `userId` is
never null on insert; it goes null only when that user is deleted, which is what
the foreign key is for, and is why the column cannot be `NOT NULL`. The comment
said "for entries no user caused", which described a scheduled run and is now
unreachable.

Two more leftovers in the same file:

- The `activityResourceTypes` doc still explained how an execution entry points
  at its workflow. It now carries the note that `resourceType` equals `category`
  for every entry written today, and why the column stays anyway.
- The "deliberately not a foreign key" rationale sat above `resourceType` while
  describing `resourceId`. Moved to the column it is about.
2026-09-01 18:35:52 +02:00
Arvin Ansari
91f88b1423
fix(core): Read a zero activity retention cap as unlimited (no-changelog)
`deleteBeyondNewest(0)` deleted every row. n8n reads a zero retention count the
other way: `EXECUTIONS_DATA_PRUNE_MAX_COUNT` documents `0` as unlimited. A cap
wired from a config on that convention would therefore empty the table instead
of disabling the backstop. It now returns without deleting, and a real-database
test holds the table at three rows.

Four other review points:

- `deleteInBatches` took a batch predicate and a scope as separate arguments, so
  a caller could pass a predicate that dropped its own scope. It now takes the
  scope and an optional id bound, and adds the per-batch bound to that bound
  instead of replacing it.
- `typeVersion` said it is bumped when the shape of `data` changes, but the only
  write path could not set it. It is on the input now.
- Comments still described executions after they left the vocabulary: `failed`
  and `succeeded` verbs, a scheduled run as the reason for a null `userId`, and a
  run status in `data`. Two were Postgres column comments, so the schema docs are
  regenerated.
- `resourceType` equals `category` for every entry written today. The comment now
  says so, and says why the column stays: the two come apart for an entry about
  one kind of thing that points at another, such as a source-control pull.
2026-09-01 18:35:52 +02:00
Arvin Ansari
b73e79a179
refactor(core): Drop executions from the activity category vocabulary (no-changelog)
Review feedback on the migration: a row per workflow execution is too costly for
large instances. It is also redundant. `execution_entity` already records every
run and indexes `(workflowId, status, id)` for exactly the read a feed wants, so
an activity row per run duplicates an existing row at the same cardinality and
pays an insert on the execution hot path, on every worker. A reader queries that
table instead.

`category` therefore narrows to `workflow` and `credential` — the events with no
queryable home. A deleted workflow is the case that matters: `workflow_history`
cascades on delete, so nothing else records that the workflow existed or that it
was removed.

The trade-off is that the execution view now ends where `EXECUTIONS_DATA_MAX_AGE`
ends, 336 hours by default. That suits a recent-activity feed. A longer horizon
should copy the `insights` raw-to-period compaction, not a row per run.
2026-09-01 18:35:51 +02:00
Arvin Ansari
2ffe0472d9
chore(core): Move the activity event migration above the current head (no-changelog)
Master landed `CreateAgentBackgroundJobTable1788191436461` above this migration.
The `migration-timestamp` rule requires every added migration to sort after all
others, so the file moves to 1788253087010.

The rebase also touched the two generated schema READMEs. Both are regenerated
rather than merged by hand.
2026-09-01 18:35:51 +02:00
Arvin Ansari
3f37308d01
docs(core): Say what the activity category column is for (no-changelog)
`category` was documented as "Resource kind an entry is about", which is
`resourceType`'s job. Two columns whose docs claim the same role is how someone
eventually writes `execution` into `resourceType`.

They are different axes. `category` is what happened; `resourceType` is what the
entry points at. The two coincide for `workflow` and `credential` and diverge for
the rest — an execution and an eval run both point at a workflow, and only
`category` separates either from a save. `action` cannot stand in, because a real
run and an eval run share `succeeded` / `failed`.
2026-09-01 18:35:51 +02:00
Arvin Ansari
72698060b3
refactor(core): Ship the activity event table as a single migration (no-changelog)
The `migration-timestamp` code-health rule rejects a PR that adds more than one
migration: every added file must sort above every other, including its own
sibling, so the lower of the two always violates. The rule's own test named
"accepts a multi-migration PR" asserts exactly that in its body. Rebasing also
put both timestamps below `CreateTypeAvailabilityPolicyTables1787841960965`,
which landed on master meanwhile, so both needed renaming regardless.

Collapsing to one file forced a choice the ticket left open, and the resource
index is the part that goes. The ticket's own design note says it "arrives with
the read that needs it, not before", and nothing reads it here — so the index,
its decorator, `findByResource` and their tests are all deferred to the reader.
That leaves the two indexes each justified by a foreign key as well as a read.

The create-table migration is unchanged apart from its timestamp; it never
created the resource index.
2026-09-01 18:35:51 +02:00
Arvin Ansari
9bd83fa52d
refactor(core): Narrow the activity event repository to its write path (no-changelog)
Review follow-ups on the activity event table.

- `record` no longer accepts an `EntityManager`. Handing a driver handle to
  callers is the leak `BaseRepository` and `TransactionRunner` exist to
  prevent, and no caller wanted it: an entry describes something that already
  happened, so it must not roll back with the operation that produced it.
- Drop `findById` and `findProjectIdForResource`. Both are reader work, both
  arrived with no caller and no test.
- `projectIds` is required on a feed query. It is the access boundary, and an
  omitted scope read every project on the instance. A comment saying "required"
  is not an access check.
- A zero retention cap deletes everything instead of asking the driver for a
  negative offset.

Two comments described mechanisms that do not hold. Pruning deletes the oldest
rows, so it never frees the highest SQLite rowid; only emptying the table does.
And a project deletion cannot be recorded against the project, because the
resource vocabulary has no entry for one.
2026-09-01 18:35:51 +02:00
Arvin Ansari
573cd33fdd
feat(core): Add the activity event table and its migrations (no-changelog)
Append-only record of what recently happened on an instance: an
`ActivityEvent` entity, the `activity_event` table, and a repository with
the single write path plus the two retention deletes.

Nothing reads or writes the table yet, so this ships and rolls back
independently of any behaviour change.

It lives in core `@n8n/db` rather than a module: a record of what changed
on the instance is not specific to one consumer, and scoping it to one
would make every later reader either cross a module boundary or build a
second log.

Three decisions worth keeping:

- `resourceId` has no foreign key. An entry has to outlive what it
  describes — a workflow deletion is the entry most worth keeping, and a
  cascade erases it exactly when it becomes interesting.
- No CHECK on `category` or `action`. A feed covers more kinds with every
  feature, and each widening is another SQLite table recreation. The
  single writer is a typed relay, so the compiler already rejects a value
  outside the union.
- Two indexes on creation, `(projectId, id)` and `(userId, id)`, each
  justified by a read and a foreign key. The per-resource index lands in
  its own migration.

Index assertions read the index DDL back rather than going through
`getTable()`, which returns index columns alphabetically on Postgres and
so would confirm a column order it never checked.
2026-09-01 18:35:50 +02:00
Eugene
4285d2063f
feat(core): Add background execution mode for sub-agent delegation (#37209)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-09-01 08:08:24 +00:00
Guillaume Jacquart
37045ce3bd
feat(core): Add node type policy tables and repositories (no-changelog) (#37254)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 14:40:11 +00:00
Guillaume Jacquart
380788fd9a
fix(core): Bind OAuth token grants to their approved resource (#37122)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 12:47:45 +00:00
Benjamin Schroth
6b0de0d60f
fix(core): Report and reconcile agent channel startup failures (#36578)
Co-authored-by: Danny Martini <danny@n8n.io>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 14:35:15 +00:00
Kai
ee7584255f
feat(core): Loosen the workflow review activity schema for cause events (no-changelog) (#36376)
Co-authored-by: Jan K. <jan.kalkan@n8n.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 08:47:02 +00:00
Irénée
d42484b7f6
feat(core): Add project Git connection table (no-changelog) (#36549)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-19 07:21:32 +00:00
Benjamin Schroth
3d70ae7fc4
fix(core): Run agent scheduled tasks in the timezone they were authored in (#36226) 2026-08-18 14:21:46 +00:00
Irénée
9c947996da
feat(core): Add Git connection database table (no-changelog) (#36268)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-18 13:54:47 +00:00
Robin Braumann
d551999c6c
fix(core): Surface failures in agent sessions (#36492)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 13:07:10 +00:00
Anne Aguirre
87e8b9c58f
fix(ai-builder): Fix for autosave and publish events issues (#36241)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-18 09:17:27 +00:00
Emilia
026cee3507
feat(core): Coalesce a Schedule Trigger node's catch-up runs after downtime (#35524)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Lorent Lempereur <lorent.lempereur@n8n.io>
2026-08-14 13:04:09 +00:00
Mike Repeć
1a12af601b
fix(core): Report the real activation mode for triggers activated via the publication outbox (#36123)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-12 13:17:53 +00:00
Emilia
93ff542e92
feat(core): Add poller_state table for durable poll trigger cursors (no-changelog) (#35128)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Lorent Lempereur <lorent.lempereur@n8n.io>
2026-08-11 16:31:00 +00:00
Jan Kalkan
41d54e77f1
feat(core): Add workflow review activity log tables and migration (no-changelog) (#35517)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Sandra Zollner <sandra.zollner@n8n.io>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-11 12:25:46 +00:00
Robin Braumann
4e6fc65f55
feat(core): Add Discord as an agent chat channel (#35331)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-06 06:09:43 +00:00
Michael Drury
a74c6fd11f
fix(core): Show Agent references in credential usage (#35409) 2026-08-05 15:54:00 +00:00
Robin Braumann
1546c95485
feat(core): Persist agent session timelines during execution (#35490)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-05 08:12:58 +00:00
Robin Braumann
89c9be6266
feat(core): Emit once-per-agent setup completion telemetry (#35359)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-03 11:00:37 +00:00
Eugene
0932806c05
feat: Support inbound binary attachments for agents (no-changelog) (#34869)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 14:20:06 +00:00
Emilia
8672d9567c
feat(core): Add a misfire policy to the durable scheduler (#35075)
Some checks are pending
CI: Master (Build, Test, Lint) / Build for Github Cache (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (22.22.3) (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (24.18.0) (push) Waiting to run
CI: Master (Build, Test, Lint) / Lint (push) Waiting to run
CI: Master (Build, Test, Lint) / Performance (push) Waiting to run
CI: Master (Build, Test, Lint) / Notify Slack on failure (push) Blocked by required conditions
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 10:10:31 +00:00
Robin Braumann
4a05044bf5
refactor(core): Replace agent knowledge base binary data storage with blob storage (no-changelog) (#34985)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-28 13:36:27 +00:00
Andreas Fitzek
4f0a218e2d
feat(core): Add on-demand OAuth clients and protected resources for form triggers (no-changelog) (#34903) 2026-07-28 12:46:57 +00:00
RomanDavydchuk
48c0e70f14
fix(core): Support fractional community node versions with PostgreSQL (#34717) 2026-07-27 15:36:08 +00:00
Svetoslav Dekov
fdd4e33f9c
feat(core): Add availableInMCP column to agents (#34665)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 14:09:04 +00:00
Arvin A
e5bb60f663
feat(core): Add agent-scoped eval data model and migration (no-changelog) (#34657) 2026-07-24 12:37:53 +00:00
Albert Alises
13becf336c
feat(core): Add instance credential database schema (#34709)
Co-authored-by: Danny Martini <danny@n8n.io>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 09:37:33 +00:00
Robin Braumann
0b4bbd05b8
feat(core): Add storedAt column to agent_execution (#34858)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 08:57:18 +00:00
Sandra Zollner
156ac00120
feat(core): Add workflow review request entities and migration scripts (#34062)
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: James Gee <1285296+geemanjs@users.noreply.github.com>
Co-authored-by: kgrhartlage <kai.hartlage@n8n.io>
2026-07-21 12:57:39 +00:00
Raúl Gómez Morales
865142f5da
feat(core): Sweep interrupted Instance AI runs to a terminal state (no-changelog) (#34183)
Co-authored-by: Danny Martini <danny@n8n.io>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 10:37:28 +00:00
Lorent Lempereur
e22680b99f
fix(core): Close the durable scheduler's record-then-dispatch effect boundary (#34014)
Co-authored-by: Emilia <100027345+sovietspaceship@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 09:47:10 +00:00
mfsiega
c761c4da9b
feat(core): Add trigger reconciliation to recover missed activations (no-changelog) (#33577)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Danny Martini <danny@n8n.io>
2026-07-14 14:40:33 +00:00
Ricardo Espinoza
c3ca9a36da
feat(editor): Add scope selection to MCP OAuth consent screen (#33710)
Co-authored-by: Danny Martini <danny@n8n.io>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 13:21:14 +00:00
Raúl Gómez Morales
05b412cd28
feat(core): Add the Instance AI durable event-log store and writer (no-changelog) (#33910)
Co-authored-by: Danny Martini <danny@n8n.io>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 11:12:31 +00:00
Lorent Lempereur
fa7e97130b
feat(core): Add recurring_cron schedule kind to the durable scheduler (no-changelog) (#33858) 2026-07-10 12:48:20 +00:00
Iván Ovejero
6509d774aa
perf(core): Reduce DB reads for global credentials check (#33918) 2026-07-09 13:31:51 +00:00
Iván Ovejero
378710072f
perf(core): Aggregate workflow statistics to avoid hot-row contention (#33045) 2026-07-06 11:11:18 +00:00
Lorent Lempereur
f008844d75
feat(core): Add durable scheduler database schema (no-changelog) (#33315)
Co-authored-by: Emilia <100027345+sovietspaceship@users.noreply.github.com>
2026-07-01 13:12:59 +00:00
Savelii
4290e8461a
feat(editor): Show private credential icon on execution list runs (#32957)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 14:06:54 +00:00
mfsiega
4979df1970
feat(core): Persist per-trigger workflow publication status (no-changelog) (#33191)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 09:02:00 +00:00
yehorkardash
bc3fe3eaa6
refactor(core): Drop redundant agent execution columns (#32862) 2026-06-30 07:36:26 +00:00
bjorger
4231ae8124
refactor(core): Remove top-level agent description (no-changelog) (#32922)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-24 14:41:43 +00:00