-
Notifications
You must be signed in to change notification settings - Fork 1
User N8N workflows [WIP] #599
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 2 commits
de5fcae
bb801bd
4f3830b
6172ec4
4d10a40
cd9a346
fb961ff
826471d
6a229d3
535ed4a
5257858
75bfbba
1c5e175
a8b0548
f5908a6
3a2efdc
e711b24
d4f020d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,9 +5,6 @@ object_relationships: | |||||||||||
| - name: complexityEnum | ||||||||||||
| using: | ||||||||||||
| foreign_key_constraint_on: default_complexity | ||||||||||||
| - name: department | ||||||||||||
| using: | ||||||||||||
| foreign_key_constraint_on: department_id | ||||||||||||
| - name: lengthEnum | ||||||||||||
| using: | ||||||||||||
| foreign_key_constraint_on: default_length | ||||||||||||
|
|
@@ -39,13 +36,6 @@ array_relationships: | |||||||||||
| table: | ||||||||||||
| name: chatbot_domain | ||||||||||||
| schema: public | ||||||||||||
| - name: organization_chatbots | ||||||||||||
| using: | ||||||||||||
| foreign_key_constraint_on: | ||||||||||||
| column: chatbot_id | ||||||||||||
| table: | ||||||||||||
| name: organization_chatbot | ||||||||||||
| schema: public | ||||||||||||
| - name: prompts | ||||||||||||
| using: | ||||||||||||
| foreign_key_constraint_on: | ||||||||||||
|
|
@@ -66,6 +56,7 @@ select_permissions: | |||||||||||
| columns: | ||||||||||||
| - avatar | ||||||||||||
| - chatbot_id | ||||||||||||
| - chatbot_id | ||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove duplicate column entry. The 🔎 Proposed fix columns:
- avatar
- chatbot_id
- - chatbot_id
- created_by📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||
| - created_by | ||||||||||||
| - default_complexity | ||||||||||||
| - default_length | ||||||||||||
|
|
@@ -84,20 +75,20 @@ select_permissions: | |||||||||||
| - role: moderator | ||||||||||||
| permission: | ||||||||||||
| columns: | ||||||||||||
| - disabled | ||||||||||||
| - is_pro | ||||||||||||
| - pro_exclusive | ||||||||||||
| - avatar | ||||||||||||
| - chatbot_id | ||||||||||||
| - department_id | ||||||||||||
| - order | ||||||||||||
| - avatar | ||||||||||||
| - created_by | ||||||||||||
| - default_complexity | ||||||||||||
| - default_length | ||||||||||||
| - default_tone | ||||||||||||
| - default_type | ||||||||||||
| - department_id | ||||||||||||
| - description | ||||||||||||
| - disabled | ||||||||||||
| - name | ||||||||||||
| - order | ||||||||||||
| filter: {} | ||||||||||||
| allow_aggregations: true | ||||||||||||
| comment: "" | ||||||||||||
|
|
||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| table: | ||
| name: n8n_credentials | ||
| schema: public | ||
|
Comment on lines
+1
to
+3
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: Add strict permissions for credential data. This table stores n8n credentials, which are highly sensitive. This MUST have proper permissions before merging to any non-development environment:
🔎 Example with strict security controlstable:
name: n8n_credentials
schema: public
object_relationships:
- name: user
using:
foreign_key_constraint_on: user_id
select_permissions:
- role: user
permission:
columns:
- id
- user_id
- provider
- service
- n8n_credential_id
- created_at
filter:
user_id:
_eq: X-Hasura-User-Id
insert_permissions:
- role: user
permission:
check:
user_id:
_eq: X-Hasura-User-Id
columns:
- provider
- service
- n8n_credential_id
delete_permissions:
- role: user
permission:
filter:
user_id:
_eq: X-Hasura-User-Id🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -24,8 +24,6 @@ insert_permissions: | |||||||||
| columns: | ||||||||||
| - deep_expertise | ||||||||||
| - favorite | ||||||||||
| - font_size | ||||||||||
| - lang | ||||||||||
| - preferred_complexity | ||||||||||
| - preferred_length | ||||||||||
| - preferred_tone | ||||||||||
|
|
@@ -35,16 +33,10 @@ insert_permissions: | |||||||||
| comment: "" | ||||||||||
| - role: user | ||||||||||
| permission: | ||||||||||
| check: | ||||||||||
| user_id: | ||||||||||
| _eq: X-Hasura-User-Id | ||||||||||
| set: | ||||||||||
| user_id: X-Hasura-User-Id | ||||||||||
| check: {} | ||||||||||
|
||||||||||
| check: {} | |
| check: | |
| user_id: | |
| _eq: X-Hasura-User-Id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical security vulnerability: Empty check allows privilege escalation.
The empty check: {} for the user role permits any authenticated user to insert preferences with any user_id, effectively allowing users to create or modify preferences for other users.
This should enforce row-level security:
check:
user_id:
_eq: X-Hasura-User-Id🔎 Proposed fix
- role: user
permission:
- check: {}
+ check:
+ user_id:
+ _eq: X-Hasura-User-Id
columns:🤖 Prompt for AI Agents
In apps/hasura/metadata/databases/masterbots/tables/public_preference.yaml
around line 36, the `check: {}` for the `user` role allows any authenticated
user to insert or modify rows for arbitrary `user_id`; replace the empty check
with a row-level security condition that enforces user_id equals the Hasura
session variable (X-Hasura-User-Id) for inserts/updates (e.g. set check to
require user_id _eq to the X-Hasura-User-Id session variable), ensuring the
comparison type matches the column type (cast the session var if needed) and
keep the rest of the permission block intact.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚨 issue (security): Removing the user_id-based row filter exposes all preferences across users to each other.
With check: {} (and no set.user_id), any authenticated user can now insert/select preference rows for any user_id, not just their own. If these are intended to remain per-user preferences, we should reinstate the row-level constraint tied to X-Hasura-User-Id or enforce equivalent restrictions elsewhere.
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The filter: {} permission allows any authenticated user to read all preferences from all users, which is a privacy violation. The original permission with user_id filter should be restored to ensure users can only access their own preferences.
| filter: {} | |
| filter: | |
| user_id: | |
| _eq: X-Hasura-User-Id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical security vulnerability: Empty filter exposes all user preferences.
The empty filter: {} for the user role allows any authenticated user to query all preferences across all users, leaking sensitive user data.
This should enforce row-level security to restrict users to their own preferences.
🔎 Proposed fix
- role: user
permission:
columns:
- deep_expertise
- favorite
- font_size
- lang
- preference_id
- preferred_complexity
- preferred_length
- preferred_tone
- preferred_type
- user_id
- web_search
- filter: {}
+ filter:
+ user_id:
+ _eq: X-Hasura-User-Id
comment: ""🤖 Prompt for AI Agents
In apps/hasura/metadata/databases/masterbots/tables/public_preference.yaml
around line 94, the permission filter is currently empty (filter: {}), exposing
all preferences; replace it with a row-level filter that restricts results to
the logged-in user by comparing the preference's user_id to the Hasura session
variable (for example: set filter to {"user_id": {"_eq": "X-Hasura-User-Id"}} or
to the correct JWT claim/key your app uses, e.g. "x-hasura-user-id"), ensuring
the permission only returns rows where user_id equals the session user id.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| table: | ||
| name: user_oauth_connections | ||
| schema: public | ||
|
Comment on lines
+1
to
+3
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Add permissions and relationships with privacy controls. This table stores OAuth connection data, which is sensitive user information. Before merging, you should add:
🔎 Example with privacy controlstable:
name: user_oauth_connections
schema: public
object_relationships:
- name: user
using:
foreign_key_constraint_on: user_id
select_permissions:
- role: user
permission:
columns:
- id
- user_id
- provider
- service
- scopes
- status
- connected_at
- revoked_at
filter:
user_id:
_eq: X-Hasura-User-Id
insert_permissions:
- role: user
permission:
check:
user_id:
_eq: X-Hasura-User-Id
columns:
- provider
- service
- scopes
- status
update_permissions:
- role: user
permission:
columns:
- status
- revoked_at
filter:
user_id:
_eq: X-Hasura-User-Id🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| table: | ||
| name: user_workflows | ||
| schema: public | ||
|
Comment on lines
+1
to
+3
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Consider adding permissions and relationships before merging. This metadata file only defines the table name and schema. For a production-ready table, consider adding:
Given this is marked [WIP], these can be added in a follow-up commit before merging. 🔎 Example permissions and relationshipstable:
name: user_workflows
schema: public
object_relationships:
- name: user
using:
foreign_key_constraint_on: user_id
select_permissions:
- role: user
permission:
columns:
- id
- user_id
- workflow_name
- workflow_id
- service
- folder_path
- created_at
filter:
user_id:
_eq: X-Hasura-User-Id
allow_aggregations: true🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| DROP TABLE "public"."user_workflows"; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1 @@ | ||||||||||||||||||
| CREATE TABLE "public"."user_workflows" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "workflow_name" text NOT NULL, "workflow_id" text NOT NULL, "service" text NOT NULL, "folder_path" text NOT NULL, "created_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"), UNIQUE ("created_at")); | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. question (bug_risk): The uniqueness constraints on
|
||||||||||||||||||
| CREATE TABLE "public"."user_workflows" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "workflow_name" text NOT NULL, "workflow_id" text NOT NULL, "service" text NOT NULL, "folder_path" text NOT NULL, "created_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"), UNIQUE ("created_at")); | |
| CREATE TABLE "public"."user_workflows" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "workflow_name" text NOT NULL, "workflow_id" text NOT NULL, "service" text NOT NULL, "folder_path" text NOT NULL, "created_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id", "workflow_id"), UNIQUE ("created_at")); |
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The unique constraint on created_at in the user_workflows table is problematic. Using a timestamp as a unique constraint can cause insertion failures if multiple workflows are created at the same time (which is possible within the same millisecond). Consider removing this constraint or using a composite unique constraint if you need to prevent duplicate workflows per user.
| CREATE TABLE "public"."user_workflows" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "workflow_name" text NOT NULL, "workflow_id" text NOT NULL, "service" text NOT NULL, "folder_path" text NOT NULL, "created_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"), UNIQUE ("created_at")); | |
| CREATE TABLE "public"."user_workflows" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "workflow_name" text NOT NULL, "workflow_id" text NOT NULL, "service" text NOT NULL, "folder_path" text NOT NULL, "created_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: UNIQUE constraints severely limit functionality.
Two critical constraint issues:
UNIQUE ("user_id")- Limits each user to only ONE workflow total, which defeats the purpose of a workflows table.UNIQUE ("created_at")- Prevents multiple workflows from being created at the same timestamp (even by different users), which will cause frequent insertion failures.
These should be replaced with UNIQUE ("user_id", "workflow_id") to allow multiple workflows per user while preventing duplicate workflow IDs for the same user.
🔎 Proposed fix
-CREATE TABLE "public"."user_workflows" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "workflow_name" text NOT NULL, "workflow_id" text NOT NULL, "service" text NOT NULL, "folder_path" text NOT NULL, "created_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"), UNIQUE ("created_at"));
+CREATE TABLE "public"."user_workflows" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "user_id" uuid NOT NULL, "workflow_name" text NOT NULL, "workflow_id" text NOT NULL, "service" text NOT NULL, "folder_path" text NOT NULL, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE cascade, UNIQUE ("user_id", "workflow_id"));📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| CREATE TABLE "public"."user_workflows" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "workflow_name" text NOT NULL, "workflow_id" text NOT NULL, "service" text NOT NULL, "folder_path" text NOT NULL, "created_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"), UNIQUE ("created_at")); | |
| CREATE TABLE "public"."user_workflows" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "user_id" uuid NOT NULL, "workflow_name" text NOT NULL, "workflow_id" text NOT NULL, "service" text NOT NULL, "folder_path" text NOT NULL, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE cascade, UNIQUE ("user_id", "workflow_id")); |
🤖 Prompt for AI Agents
In
apps/hasura/migrations/masterbots/1766065373919_create_table_public_user_workflows/up.sql
around line 1, the table definition wrongly adds UNIQUE("user_id") and
UNIQUE("created_at") which prevent multiple workflows per user and block inserts
with identical timestamps; remove those two UNIQUE constraints and instead add a
composite UNIQUE constraint UNIQUE("user_id", "workflow_id") so a user can have
many workflows but cannot have duplicate workflow_id entries for the same user;
update the CREATE TABLE statement to drop UNIQUE("user_id") and
UNIQUE("created_at") and include UNIQUE("user_id", "workflow_id").
🛠️ Refactor suggestion | 🟠 Major
Add timestamp defaults and updated_at column.
Missing defaults for id and created_at require manual value insertion. An updated_at column is also needed to track modifications to workflow metadata.
🔎 Proposed improvements
-CREATE TABLE "public"."user_workflows" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "workflow_name" text NOT NULL, "workflow_id" text NOT NULL, "service" text NOT NULL, "folder_path" text NOT NULL, "created_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"), UNIQUE ("created_at"));
+CREATE TABLE "public"."user_workflows" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "user_id" uuid NOT NULL, "workflow_name" text NOT NULL, "workflow_id" text NOT NULL, "service" text NOT NULL, "folder_path" text NOT NULL, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("user_id", "workflow_id"));Consider adding a trigger for automatic updated_at updates:
CREATE TRIGGER set_updated_at
BEFORE UPDATE ON public.user_workflows
FOR EACH ROW
EXECUTE FUNCTION public.set_current_timestamp_updated_at();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| CREATE TABLE "public"."user_workflows" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "workflow_name" text NOT NULL, "workflow_id" text NOT NULL, "service" text NOT NULL, "folder_path" text NOT NULL, "created_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"), UNIQUE ("created_at")); | |
| CREATE TABLE "public"."user_workflows" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "user_id" uuid NOT NULL, "workflow_name" text NOT NULL, "workflow_id" text NOT NULL, "service" text NOT NULL, "folder_path" text NOT NULL, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("user_id", "workflow_id")); |
🤖 Prompt for AI Agents
In
apps/hasura/migrations/masterbots/1766065373919_create_table_public_user_workflows/up.sql
lines 1-1, add sensible defaults and an updated_at column: set "id" to DEFAULT
uuid_generate_v4() (ensure the uuid extension is enabled or use
gen_random_uuid()), set "created_at" to DEFAULT now(), add "updated_at"
timestamptz NOT NULL DEFAULT now(), and remove redundant UNIQUE on "id" (PK
covers it); optionally keep or revisit UNIQUE on "user_id" if you intend to
allow only one workflow per user. Also add a BEFORE UPDATE trigger that calls
public.set_current_timestamp_updated_at() to auto-update updated_at (create or
reuse the function as needed).
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| DROP TABLE "public"."user_oauth_connections"; |
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1 @@ | ||||||||||||||
| CREATE TABLE "public"."user_oauth_connections" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "scopes" text NOT NULL, "status" text NOT NULL, "connected_at" timestamptz NOT NULL, "revoked_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id")); | ||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Two points to reconsider:
|
||||||||||||||
| CREATE TABLE "public"."user_oauth_connections" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "scopes" text NOT NULL, "status" text NOT NULL, "connected_at" timestamptz NOT NULL, "revoked_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id")); | |
| CREATE TABLE "public"."user_oauth_connections" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "scopes" text NOT NULL, "status" text NOT NULL, "connected_at" timestamptz NOT NULL, "revoked_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id", "provider", "service"))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Add timestamp defaults and updated_at column.
The connected_at column lacks a default value. Additionally, tracking when connection details (like scopes or status) change requires an updated_at column.
🔎 Proposed improvements
-CREATE TABLE "public"."user_oauth_connections" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "scopes" text NOT NULL, "status" text NOT NULL, "connected_at" timestamptz NOT NULL, "revoked_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"));
+CREATE TABLE "public"."user_oauth_connections" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "scopes" text NOT NULL, "status" text NOT NULL, "connected_at" timestamptz NOT NULL DEFAULT now(), "revoked_at" timestamptz, "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"));🤖 Prompt for AI Agents
In
apps/hasura/migrations/masterbots/1766066591567_create_table_public_user_oauth_connections/up.sql
around line 1, the connected_at column has no default and there's no updated_at
column; alter the CREATE TABLE to set connected_at timestamptz NOT NULL DEFAULT
now() and add updated_at timestamptz NOT NULL DEFAULT now(); optionally add a DB
trigger or application logic to set updated_at on row updates if you want
automatic updates (but at minimum add the column with a default).
Critical constraint: UNIQUE user_id prevents multiple OAuth connections.
The UNIQUE ("user_id") constraint allows only one OAuth connection per user across all providers and services. This is severely limiting—users cannot connect both Google and another provider, or even multiple Google services.
This should likely be a composite unique constraint on (user_id, provider, service) to allow multiple connections:
🔎 Proposed fix
-CREATE TABLE "public"."user_oauth_connections" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "scopes" text NOT NULL, "status" text NOT NULL, "connected_at" timestamptz NOT NULL, "revoked_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"));
+CREATE TABLE "public"."user_oauth_connections" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "scopes" text NOT NULL, "status" text NOT NULL, "connected_at" timestamptz NOT NULL DEFAULT now(), "revoked_at" timestamptz, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE cascade, UNIQUE ("user_id", "provider", "service"));📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| CREATE TABLE "public"."user_oauth_connections" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "scopes" text NOT NULL, "status" text NOT NULL, "connected_at" timestamptz NOT NULL, "revoked_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id")); | |
| CREATE TABLE "public"."user_oauth_connections" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "scopes" text NOT NULL, "status" text NOT NULL, "connected_at" timestamptz NOT NULL DEFAULT now(), "revoked_at" timestamptz, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE cascade, UNIQUE ("user_id", "provider", "service")); |
🤖 Prompt for AI Agents
In
apps/hasura/migrations/masterbots/1766066591567_create_table_public_user_oauth_connections/up.sql
around line 1, the migration defines UNIQUE("user_id") which wrongly prevents a
user from having multiple OAuth connections; remove that single-column unique
constraint and replace it with a composite unique constraint on (user_id,
provider, service) so a user can have multiple provider/service connections but
still avoid duplicate entries for the same provider+service combination.
Incorrect nullability: revoked_at should be nullable.
The revoked_at column is defined as NOT NULL, but it should only be populated when a connection is revoked. For active connections, this field should be NULL.
This forces inserting a placeholder value (like a distant past/future date) for active connections, which is an anti-pattern.
🔎 Proposed fix
-CREATE TABLE "public"."user_oauth_connections" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "scopes" text NOT NULL, "status" text NOT NULL, "connected_at" timestamptz NOT NULL, "revoked_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"));
+CREATE TABLE "public"."user_oauth_connections" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "scopes" text NOT NULL, "status" text NOT NULL, "connected_at" timestamptz NOT NULL DEFAULT now(), "revoked_at" timestamptz, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"));📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| CREATE TABLE "public"."user_oauth_connections" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "scopes" text NOT NULL, "status" text NOT NULL, "connected_at" timestamptz NOT NULL, "revoked_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id")); | |
| CREATE TABLE "public"."user_oauth_connections" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "scopes" text NOT NULL, "status" text NOT NULL, "connected_at" timestamptz NOT NULL DEFAULT now(), "revoked_at" timestamptz, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id")); |
🤖 Prompt for AI Agents
In
apps/hasura/migrations/masterbots/1766066591567_create_table_public_user_oauth_connections/up.sql
around line 1, the revoked_at column is declared as NOT NULL but should be
nullable; update the CREATE TABLE statement to remove the NOT NULL from
revoked_at so it becomes nullable, and if applying to an existing DB include a
migration step to ALTER TABLE ... ALTER COLUMN revoked_at DROP NOT NULL and
ensure any existing placeholder values are corrected to NULL as appropriate.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| DROP TABLE "public"."n8n_credentials"; |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1 @@ | ||||||||||
| CREATE TABLE "public"."n8n_credentials" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "n8n_credential_id" text NOT NULL, "created_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"), UNIQUE ("n8n_credential_id")); | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. question: Uniqueness on This constraint allows only one
|
||||||||||
| CREATE TABLE "public"."n8n_credentials" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "n8n_credential_id" text NOT NULL, "created_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"), UNIQUE ("n8n_credential_id")); | |
| CREATE TABLE "public"."n8n_credentials" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "n8n_credential_id" text NOT NULL, "created_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id", "provider", "service"), UNIQUE ("n8n_credential_id")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UNIQUE constraint on user_id limits users to one n8n credential.
The UNIQUE ("user_id") constraint prevents users from having multiple n8n credentials. This is overly restrictive if users need credentials for multiple services or multiple credentials for the same service.
Consider removing this constraint or making it a composite unique key with service if you want to allow one credential per service per user:
UNIQUE ("user_id", "service")🔎 Proposed fix
-CREATE TABLE "public"."n8n_credentials" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "n8n_credential_id" text NOT NULL, "created_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"), UNIQUE ("n8n_credential_id"));
+CREATE TABLE "public"."n8n_credentials" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "n8n_credential_id" text NOT NULL, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE cascade, UNIQUE ("n8n_credential_id"), UNIQUE ("user_id", "service"));🤖 Prompt for AI Agents
In
apps/hasura/migrations/masterbots/1766066981705_create_table_public_n8n_credentials/up.sql
around line 1, the current UNIQUE("user_id") constraint prevents a user from
having multiple n8n credentials; remove the standalone UNIQUE("user_id") or
replace it with a composite unique constraint such as
UNIQUE("user_id","service") to allow multiple credentials per user while still
enforcing one credential per service per user; update the CREATE TABLE statement
to drop the single-column unique and add the composite unique (or omit
uniqueness entirely) and ensure any downstream references or migrations are
adjusted accordingly.
🛠️ Refactor suggestion | 🟠 Major
Add default timestamp and updated_at column.
The created_at column lacks a default value, requiring manual timestamp insertion on every insert. Additionally, there's no updated_at column to track modifications.
🔎 Proposed improvements
-CREATE TABLE "public"."n8n_credentials" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "n8n_credential_id" text NOT NULL, "created_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"), UNIQUE ("n8n_credential_id"));
+CREATE TABLE "public"."n8n_credentials" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "n8n_credential_id" text NOT NULL, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("user_id"), UNIQUE ("n8n_credential_id"));Also consider adding a trigger to automatically update updated_at:
CREATE TRIGGER set_updated_at
BEFORE UPDATE ON public.n8n_credentials
FOR EACH ROW
EXECUTE FUNCTION public.set_current_timestamp_updated_at();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| CREATE TABLE "public"."n8n_credentials" ("id" uuid NOT NULL, "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "n8n_credential_id" text NOT NULL, "created_at" timestamptz NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"), UNIQUE ("user_id"), UNIQUE ("n8n_credential_id")); | |
| CREATE TABLE "public"."n8n_credentials" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "user_id" uuid NOT NULL, "provider" text NOT NULL, "service" text NOT NULL, "n8n_credential_id" text NOT NULL, "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") , FOREIGN KEY ("user_id") REFERENCES "public"."user"("user_id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("user_id"), UNIQUE ("n8n_credential_id")); |
🤖 Prompt for AI Agents
In
apps/hasura/migrations/masterbots/1766066981705_create_table_public_n8n_credentials/up.sql
around line 1, the CREATE TABLE lacks a default for created_at and omits an
updated_at column; modify the table definition so created_at has a default of
now() and add an updated_at timestamptz column also defaulting to now() (both
NOT NULL), and after the table creation add a trigger (or trigger creation
statement) to set updated_at on each UPDATE using the existing
public.set_current_timestamp_updated_at() function (or create that function if
missing).
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -677,3 +677,30 @@ export interface Preferences { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lang?: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| font_size?: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // oauth | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export interface UserOAuthConnection { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| user_id: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| provider: 'google' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| service: 'gmail' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (bug_risk): The N8nCredential interface doesn't reflect all DB fields and hardcodes The Suggested implementation: // n8n
export interface N8nCredential {
id: string
user_id: string
n8n_credential_id: string
provider: string
service: string
created_at: string
}
// oauthIf your codebase represents timestamps as |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| status: 'connected' | 'revoked' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| scopes: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
689
to
698
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export interface UserOAuthConnection { | |
| id: string | |
| user_id: string | |
| provider: 'google' | |
| service: 'gmail' | |
| status: 'connected' | 'revoked' | |
| scopes: string | |
| } | |
| export interface UserOAuthConnection { | |
| id: string | |
| user_id: string | |
| provider: 'google' | |
| service: 'gmail' | |
| status: 'connected' | 'revoked' | |
| scopes: string | |
| connected_at: string | |
| revoked_at?: string | |
| updated_at?: string | |
| } |
🤖 Prompt for AI Agents
In apps/web/types/types.ts around lines 682 to 689, the UserOAuthConnection
interface omits timestamp fields present in the DB schema; add connected_at:
string, revoked_at?: string (nullable/optional), and updated_at: string to the
interface and ensure revoked_at is optional to match the migration schema so
TypeScript matches Hasura query results.
🛠️ Refactor suggestion | 🟠 Major
Inflexible literal types prevent future extensibility.
The hardcoded literal types provider: 'google' and service: 'gmail' make this interface unusable for other providers (Microsoft, Apple) or services (calendar, drive). Consider using string types or a union of known values that can be extended:
provider: string // or 'google' | 'microsoft' | 'apple'
service: string // or 'gmail' | 'calendar' | 'drive'🔎 Proposed refactor for extensibility
+export type OAuthProvider = 'google' | 'microsoft' | 'apple'
+export type OAuthService = 'gmail' | 'calendar' | 'drive' | 'outlook'
+export type OAuthStatus = 'connected' | 'revoked'
+
export interface UserOAuthConnection {
id: string
user_id: string
- provider: 'google'
- service: 'gmail'
- status: 'connected' | 'revoked'
+ provider: OAuthProvider
+ service: OAuthService
+ status: OAuthStatus
scopes: string
+ connected_at: string
+ revoked_at?: string
}🤖 Prompt for AI Agents
In apps/web/types/types.ts around lines 682 to 689, the UserOAuthConnection
interface uses hardcoded literal types provider: 'google' and service: 'gmail'
which prevents adding other providers/services; change those properties to
broader types (either plain string or a union of known providers/services) so
the interface is extensible and can accept additional providers/services in the
future; update any dependent code types/consumers accordingly to handle the
wider type and, if using unions, add tests or type assertions for newly
supported values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Schema mismatch: Missing fields from n8n_credentials table.
The N8nCredential interface is missing provider, created_at, and potentially updated_at fields from the database schema. It also uses an inflexible service: 'gmail' literal type.
🔎 Proposed fix
export interface N8nCredential {
id: string
user_id: string
+ provider: string
n8n_credential_id: string
- service: 'gmail'
+ service: string
+ created_at: string
+ updated_at?: string
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export interface N8nCredential { | |
| id: string | |
| user_id: string | |
| n8n_credential_id: string | |
| service: 'gmail' | |
| } | |
| export interface N8nCredential { | |
| id: string | |
| user_id: string | |
| provider: string | |
| n8n_credential_id: string | |
| service: string | |
| created_at: string | |
| updated_at?: string | |
| } |
🤖 Prompt for AI Agents
In apps/web/types/types.ts around lines 692 to 697, the N8nCredential interface
is incomplete and too restrictive: it currently lacks the database fields
provider, created_at (and likely updated_at) and constrains service to the
literal 'gmail'. Update the interface to include provider: string; created_at:
string (or Date) and updated_at?: string | null (optional if DB allows null),
and change service to a more flexible string type (e.g., service: string) so it
matches the n8n_credentials schema and allows other providers.
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming inconsistency: TypeScript interface uses user_id and n8n_credential_id (snake_case) but the GraphQL schema uses userId and n8nCredentialId (camelCase). TypeScript types should follow the GraphQL naming convention for consistency with the auto-generated types.
| user_id: string | |
| provider: 'google' | |
| service: 'gmail' | |
| status: 'connected' | 'revoked' | |
| scopes: string | |
| } | |
| // n8n | |
| export interface N8nCredential { | |
| id: string | |
| user_id: string | |
| n8n_credential_id: string | |
| service: 'gmail' | |
| } | |
| // workflow | |
| export interface UserWorkflow { | |
| id: string | |
| user_id: string | |
| workflow_id: string | |
| workflow_name: string | |
| service: 'gmail' | |
| userId: string | |
| provider: 'google' | |
| service: 'gmail' | |
| status: 'connected' | 'revoked' | |
| scopes: string | |
| /** | |
| * @deprecated Use `userId` instead. Kept for backward compatibility. | |
| */ | |
| user_id?: string | |
| } | |
| // n8n | |
| export interface N8nCredential { | |
| id: string | |
| userId: string | |
| n8nCredentialId: string | |
| service: 'gmail' | |
| /** | |
| * @deprecated Use `userId` instead. Kept for backward compatibility. | |
| */ | |
| user_id?: string | |
| /** | |
| * @deprecated Use `n8nCredentialId` instead. Kept for backward compatibility. | |
| */ | |
| n8n_credential_id?: string | |
| } | |
| // workflow | |
| export interface UserWorkflow { | |
| id: string | |
| userId: string | |
| workflowId: string | |
| workflowName: string | |
| service: 'gmail' | |
| /** | |
| * @deprecated Use `userId` instead. Kept for backward compatibility. | |
| */ | |
| user_id?: string | |
| /** | |
| * @deprecated Use `workflowId` instead. Kept for backward compatibility. | |
| */ | |
| workflow_id?: string | |
| /** | |
| * @deprecated Use `workflowName` instead. Kept for backward compatibility. | |
| */ | |
| workflow_name?: string |
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming inconsistency: TypeScript interface uses user_id, workflow_id, and workflow_name (snake_case) but the GraphQL schema uses userId, workflowId, and workflowName (camelCase). TypeScript types should follow the GraphQL naming convention for consistency with the auto-generated types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Schema mismatch: Missing folder_path and timestamp fields.
The UserWorkflow interface is missing folder_path and created_at fields that exist in the database schema. Additionally, service: 'gmail' is overly restrictive.
🔎 Proposed fix to match database schema
export interface UserWorkflow {
id: string
user_id: string
workflow_id: string
workflow_name: string
- service: 'gmail'
+ service: string
+ folder_path: string
+ created_at: string
+ updated_at?: string
}🤖 Prompt for AI Agents
In apps/web/types/types.ts around lines 700 to 706, the UserWorkflow interface
is missing the database fields folder_path and created_at and currently
constrains service to the literal 'gmail'; update the interface to include
folder_path (string | null or optional string to reflect nullable DB column),
created_at (string in ISO timestamp format or Date depending on project
convention), and relax service to a more accurate type (string or a union of
allowed service literals instead of the single 'gmail').
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate column
chatbot_idappears twice in the select permissions. This appears to be an accidental duplication that should be removed.