@polymorphism-tech/morph-spec 4.16.0 → 4.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +2 -2
  2. package/bin/morph-spec.js +3 -0
  3. package/bin/task-manager.js +999 -962
  4. package/claude-plugin.json +1 -1
  5. package/docs/CHEATSHEET.md +1 -1
  6. package/docs/QUICKSTART.md +1 -1
  7. package/framework/agents/ai-agents/vector-search-expert.md +247 -233
  8. package/framework/agents/backend/ms-agent-expert.md +1 -1
  9. package/framework/agents/backend/neon-expert.md +397 -0
  10. package/framework/agents/frontend/gsap-animator.md +131 -0
  11. package/framework/agents.json +1175 -1085
  12. package/framework/commands/morph-preflight.md +200 -192
  13. package/framework/hooks/claude-code/session-start/inject-morph-context.js +1 -1
  14. package/framework/rules/gsap-standards.md +13 -0
  15. package/framework/rules/neon-standards.md +25 -0
  16. package/framework/skills/level-0-meta/mcp-registry.json +1 -1
  17. package/framework/skills/level-0-meta/morph-agent-teams/SKILL.md +472 -472
  18. package/framework/skills/level-0-meta/morph-init/SKILL.md +11 -11
  19. package/framework/skills/level-0-meta/morph-post-implementation/SKILL.md +5 -5
  20. package/framework/skills/level-0-meta/morph-tool-usage-guide/SKILL.md +5 -5
  21. package/framework/skills/level-0-meta/morph-tool-usage-guide/references/tools-per-phase.md +7 -7
  22. package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +24 -24
  23. package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +12 -12
  24. package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +9 -9
  25. package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +1 -1
  26. package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +1 -1
  27. package/framework/skills/level-1-workflows/morph-phase-tasks/references/task-planning-patterns.md +143 -143
  28. package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +1 -1
  29. package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
  30. package/framework/standards/STANDARDS.json +184 -107
  31. package/framework/standards/ai-agents/production.md +1 -0
  32. package/framework/standards/ai-agents/setup.md +3 -2
  33. package/framework/standards/ai-agents/workflows.md +1 -0
  34. package/framework/standards/architecture/vertical-slice/vertical-slice.md +4 -4
  35. package/framework/standards/backend/database/postgresql/database.md +58 -78
  36. package/framework/standards/backend/dotnet/scalar-ui.md +172 -172
  37. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +274 -274
  38. package/framework/standards/backend/integrations/asaas/asaas-api.md +1 -1
  39. package/framework/standards/backend/integrations/clerk/clerk-auth.md +23 -21
  40. package/framework/standards/frontend/design-system/animations.md +9 -0
  41. package/framework/standards/frontend/gsap/gsap-core.md +463 -0
  42. package/framework/standards/frontend/gsap/gsap-plugins.md +294 -0
  43. package/framework/standards/frontend/gsap/gsap-scrolltrigger.md +318 -0
  44. package/framework/standards/frontend/nextjs/motion-patterns.md +1 -0
  45. package/framework/standards/frontend/nextjs/nextjs-patterns.md +47 -37
  46. package/framework/standards/infrastructure/docker/easypanel-deploy.md +4 -8
  47. package/framework/standards/infrastructure/neon/neon-pgrag.md +239 -0
  48. package/framework/standards/infrastructure/neon/neon-pgvector.md +236 -0
  49. package/framework/standards/infrastructure/neon/neon-semantic-kernel.md +310 -0
  50. package/framework/standards/infrastructure/neon/neon-setup.md +186 -0
  51. package/framework/standards/integration/mcp/mcp-tools.md +32 -34
  52. package/framework/templates/README.md +18 -18
  53. package/framework/templates/REGISTRY.json +49 -96
  54. package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
  55. package/framework/templates/code/dotnet/backend/repository.cs +148 -148
  56. package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +2 -2
  57. package/framework/templates/code/dotnet/database/vector-entity.cs +93 -0
  58. package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +1 -1
  59. package/framework/templates/code/sql/{supabase-migration.sql → postgresql-migration.sql} +8 -17
  60. package/framework/templates/code/sql/{supabase-migration.template.sql → postgresql-migration.template.sql} +10 -13
  61. package/framework/templates/code/sql/{rls-policy.sql → postgresql-rls-policy.sql} +8 -8
  62. package/framework/templates/code/typescript/contracts.ts +167 -168
  63. package/framework/templates/context/CONTEXT.md +3 -3
  64. package/framework/templates/docs/proposal.md +6 -6
  65. package/framework/templates/docs/ui-components.md +1 -1
  66. package/framework/templates/feature/decisions.md +121 -121
  67. package/framework/templates/feature/recap.md +145 -145
  68. package/framework/templates/feature/tasks.md +199 -199
  69. package/framework/templates/frontend/nextjs/gsap-scroll-section.tsx.hbs +44 -0
  70. package/framework/templates/infrastructure/docker/docker-compose.template.yml +50 -67
  71. package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
  72. package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
  73. package/framework/templates/infrastructure/docker/easypanel.template.json +46 -54
  74. package/framework/templates/infrastructure/github/README.md +56 -56
  75. package/framework/templates/integrations/semantic-kernel-neon.cs +125 -0
  76. package/framework/workflows/README.md +1 -1
  77. package/framework/workflows/docs/full-morph.md +69 -69
  78. package/package.json +1 -1
  79. package/src/commands/agents/dispatch-agents.js +19 -15
  80. package/src/commands/state/advance-phase.js +5 -0
  81. package/src/commands/tasks/task.js +3 -0
  82. package/src/core/state/state-manager.js +45 -1
  83. package/src/core/templates/template-registry.js +1 -66
  84. package/src/lib/detectors/index.js +2 -2
  85. package/src/lib/generators/architecture-scanner.js +640 -640
  86. package/src/lib/installers/mcp-installer.js +1 -1
  87. package/src/lib/tasks/task-classifier.js +15 -1
  88. package/src/lib/tasks/test-runner.js +5 -1
  89. package/src/lib/validators/content/content-validator.js +9 -10
  90. package/src/lib/validators/validation-runner.js +7 -5
  91. package/framework/agents/backend/supabase-expert.md +0 -256
  92. package/framework/rules/supabase-standards.md +0 -29
  93. package/framework/standards/infrastructure/supabase/mcp-setup.md +0 -142
  94. package/framework/standards/infrastructure/supabase/supabase-auth.md +0 -176
  95. package/framework/standards/infrastructure/supabase/supabase-custom-jwt.md +0 -206
  96. package/framework/standards/infrastructure/supabase/supabase-pgvector.md +0 -169
  97. package/framework/standards/infrastructure/supabase/supabase-rls.md +0 -184
  98. package/framework/standards/infrastructure/supabase/supabase-storage.md +0 -153
@@ -1,148 +1,148 @@
1
- // ============================================================
2
- // REPOSITORY + UNIT OF WORK TEMPLATE (VSA Pattern)
3
- // Generated by MORPH Framework
4
- // ============================================================
5
-
6
- using System.Data.Common;
7
- using Microsoft.EntityFrameworkCore;
8
- using {{pascalCase PROJECT_NAME}}.Database;
9
-
10
- namespace {{pascalCase PROJECT_NAME}}.Repository;
11
-
12
- // ============================================================
13
- // IRepository<T> — Generic repository contract
14
- // ============================================================
15
-
16
- public interface IRepository<T> where T : class
17
- {
18
- Task<IEnumerable<T>> GetAllAsync(CancellationToken cancellationToken = default);
19
- Task<T?> GetByIdAsync(object id, CancellationToken cancellationToken = default);
20
- Task<T> AddAsync(T entity, CancellationToken cancellationToken = default);
21
- Task UpdateAsync(T entity, CancellationToken cancellationToken = default);
22
- Task DeleteAsync(T entity, CancellationToken cancellationToken = default);
23
- IEnumerable<T> ExecuteQuery(string query, DbParameter[] dbParams);
24
- Task AddRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default);
25
- void RemoveRange(IEnumerable<T> entities);
26
- }
27
-
28
- // ============================================================
29
- // IUnitOfWork — Transaction boundary contract
30
- // ============================================================
31
-
32
- public interface IUnitOfWork
33
- {
34
- int Commit();
35
- void Rollback();
36
- Task<int> CommitAsync(CancellationToken cancellationToken = default);
37
- Task RollbackAsync();
38
- }
39
-
40
- // ============================================================
41
- // Repository<T> — EF Core generic repository implementation
42
- // ============================================================
43
-
44
- public class Repository<T> : IRepository<T> where T : class
45
- {
46
- private readonly ApplicationDbContext _context;
47
- private readonly DbSet<T> _dbSet;
48
-
49
- public Repository(ApplicationDbContext context)
50
- {
51
- _context = context;
52
- _dbSet = _context.Set<T>();
53
- }
54
-
55
- public async Task<IEnumerable<T>> GetAllAsync(CancellationToken cancellationToken = default)
56
- {
57
- return await _dbSet.ToListAsync(cancellationToken);
58
- }
59
-
60
- public async Task<T?> GetByIdAsync(object id, CancellationToken cancellationToken = default)
61
- {
62
- return await _dbSet.FindAsync(new[] { id }, cancellationToken);
63
- }
64
-
65
- public async Task<T> AddAsync(T entity, CancellationToken cancellationToken = default)
66
- {
67
- await _dbSet.AddAsync(entity, cancellationToken);
68
- return entity;
69
- }
70
-
71
- public Task UpdateAsync(T entity, CancellationToken cancellationToken = default)
72
- {
73
- _dbSet.Update(entity);
74
- return Task.CompletedTask;
75
- }
76
-
77
- public Task DeleteAsync(T entity, CancellationToken cancellationToken = default)
78
- {
79
- _dbSet.Remove(entity);
80
- return Task.CompletedTask;
81
- }
82
-
83
- public IEnumerable<T> ExecuteQuery(string query, DbParameter[] dbParams)
84
- {
85
- return _dbSet
86
- .FromSqlRaw(query, dbParams)
87
- .AsNoTracking()
88
- .AsEnumerable();
89
- }
90
-
91
- public async Task AddRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default)
92
- {
93
- await _dbSet.AddRangeAsync(entities, cancellationToken);
94
- }
95
-
96
- public void RemoveRange(IEnumerable<T> entities)
97
- {
98
- _dbSet.RemoveRange(entities);
99
- }
100
- }
101
-
102
- // ============================================================
103
- // UnitOfWork — EF Core transaction management
104
- // ============================================================
105
-
106
- public class UnitOfWork : IUnitOfWork
107
- {
108
- private readonly ApplicationDbContext _dataContext;
109
-
110
- public UnitOfWork(ApplicationDbContext dataContext)
111
- {
112
- _dataContext = dataContext;
113
- }
114
-
115
- public int Commit()
116
- {
117
- return _dataContext.SaveChanges();
118
- }
119
-
120
- public async Task<int> CommitAsync(CancellationToken cancellationToken = default)
121
- {
122
- return await _dataContext.SaveChangesAsync(cancellationToken);
123
- }
124
-
125
- public void Rollback()
126
- {
127
- _dataContext.Dispose();
128
- }
129
-
130
- public async Task RollbackAsync()
131
- {
132
- await _dataContext.DisposeAsync();
133
- }
134
- }
135
-
136
- // ============================================================
137
- // DI REGISTRATION
138
- // ============================================================
139
- //
140
- // In Program.cs or a DI extension method:
141
- //
142
- // builder.Services.AddDbContext<ApplicationDbContext>(options =>
143
- // options.UseSqlServer(connectionString));
144
- //
145
- // builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
146
- // builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();
147
- //
148
- // ============================================================
1
+ // ============================================================
2
+ // REPOSITORY + UNIT OF WORK TEMPLATE (VSA Pattern)
3
+ // Generated by MORPH Framework
4
+ // ============================================================
5
+
6
+ using System.Data.Common;
7
+ using Microsoft.EntityFrameworkCore;
8
+ using {{pascalCase PROJECT_NAME}}.Database;
9
+
10
+ namespace {{pascalCase PROJECT_NAME}}.Repository;
11
+
12
+ // ============================================================
13
+ // IRepository<T> — Generic repository contract
14
+ // ============================================================
15
+
16
+ public interface IRepository<T> where T : class
17
+ {
18
+ Task<IEnumerable<T>> GetAllAsync(CancellationToken cancellationToken = default);
19
+ Task<T?> GetByIdAsync(object id, CancellationToken cancellationToken = default);
20
+ Task<T> AddAsync(T entity, CancellationToken cancellationToken = default);
21
+ Task UpdateAsync(T entity, CancellationToken cancellationToken = default);
22
+ Task DeleteAsync(T entity, CancellationToken cancellationToken = default);
23
+ IEnumerable<T> ExecuteQuery(string query, DbParameter[] dbParams);
24
+ Task AddRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default);
25
+ void RemoveRange(IEnumerable<T> entities);
26
+ }
27
+
28
+ // ============================================================
29
+ // IUnitOfWork — Transaction boundary contract
30
+ // ============================================================
31
+
32
+ public interface IUnitOfWork
33
+ {
34
+ int Commit();
35
+ void Rollback();
36
+ Task<int> CommitAsync(CancellationToken cancellationToken = default);
37
+ Task RollbackAsync(CancellationToken cancellationToken = default);
38
+ }
39
+
40
+ // ============================================================
41
+ // Repository<T> — EF Core generic repository implementation
42
+ // ============================================================
43
+
44
+ public class Repository<T> : IRepository<T> where T : class
45
+ {
46
+ private readonly ApplicationDbContext _context;
47
+ private readonly DbSet<T> _dbSet;
48
+
49
+ public Repository(ApplicationDbContext context)
50
+ {
51
+ _context = context;
52
+ _dbSet = _context.Set<T>();
53
+ }
54
+
55
+ public async Task<IEnumerable<T>> GetAllAsync(CancellationToken cancellationToken = default)
56
+ {
57
+ return await _dbSet.ToListAsync(cancellationToken);
58
+ }
59
+
60
+ public async Task<T?> GetByIdAsync(object id, CancellationToken cancellationToken = default)
61
+ {
62
+ return await _dbSet.FindAsync(new[] { id }, cancellationToken);
63
+ }
64
+
65
+ public async Task<T> AddAsync(T entity, CancellationToken cancellationToken = default)
66
+ {
67
+ await _dbSet.AddAsync(entity, cancellationToken);
68
+ return entity;
69
+ }
70
+
71
+ public Task UpdateAsync(T entity, CancellationToken cancellationToken = default)
72
+ {
73
+ _dbSet.Update(entity);
74
+ return Task.CompletedTask;
75
+ }
76
+
77
+ public Task DeleteAsync(T entity, CancellationToken cancellationToken = default)
78
+ {
79
+ _dbSet.Remove(entity);
80
+ return Task.CompletedTask;
81
+ }
82
+
83
+ public IEnumerable<T> ExecuteQuery(string query, DbParameter[] dbParams)
84
+ {
85
+ return _dbSet
86
+ .FromSqlRaw(query, dbParams)
87
+ .AsNoTracking()
88
+ .AsEnumerable();
89
+ }
90
+
91
+ public async Task AddRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default)
92
+ {
93
+ await _dbSet.AddRangeAsync(entities, cancellationToken);
94
+ }
95
+
96
+ public void RemoveRange(IEnumerable<T> entities)
97
+ {
98
+ _dbSet.RemoveRange(entities);
99
+ }
100
+ }
101
+
102
+ // ============================================================
103
+ // UnitOfWork — EF Core transaction management
104
+ // ============================================================
105
+
106
+ public class UnitOfWork : IUnitOfWork
107
+ {
108
+ private readonly ApplicationDbContext _dataContext;
109
+
110
+ public UnitOfWork(ApplicationDbContext dataContext)
111
+ {
112
+ _dataContext = dataContext;
113
+ }
114
+
115
+ public int Commit()
116
+ {
117
+ return _dataContext.SaveChanges();
118
+ }
119
+
120
+ public async Task<int> CommitAsync(CancellationToken cancellationToken = default)
121
+ {
122
+ return await _dataContext.SaveChangesAsync(cancellationToken);
123
+ }
124
+
125
+ public void Rollback()
126
+ {
127
+ _dataContext.Dispose();
128
+ }
129
+
130
+ public async Task RollbackAsync(CancellationToken cancellationToken = default)
131
+ {
132
+ await _dataContext.DisposeAsync();
133
+ }
134
+ }
135
+
136
+ // ============================================================
137
+ // DI REGISTRATION
138
+ // ============================================================
139
+ //
140
+ // In Program.cs or a DI extension method:
141
+ //
142
+ // builder.Services.AddDbContext<ApplicationDbContext>(options =>
143
+ // options.UseSqlServer(connectionString));
144
+ //
145
+ // builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
146
+ // builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();
147
+ //
148
+ // ============================================================
@@ -34,7 +34,7 @@ namespace {{NAMESPACE}}.Abstractions
34
34
  {
35
35
  public interface IApiEndpoint
36
36
  {
37
- void MapEndpoint(WebApplication app);
37
+ void MapEndpoint(IEndpointRouteBuilder app);
38
38
  }
39
39
  }
40
40
 
@@ -235,7 +235,7 @@ using {{NAMESPACE}}.Extensions;
235
235
 
236
236
  internal sealed class Create{{pascalCase FEATURE_NAME}}Endpoint : IApiEndpoint
237
237
  {
238
- public void MapEndpoint(WebApplication app)
238
+ public void MapEndpoint(IEndpointRouteBuilder app)
239
239
  {
240
240
  app.MapPost("{{ROUTE}}", async (
241
241
  IHandler<Create{{pascalCase FEATURE_NAME}}Request, Result<Create{{pascalCase FEATURE_NAME}}Response>> handler,
@@ -0,0 +1,93 @@
1
+ // ============================================================
2
+ // PGVECTOR ENTITY + CONFIGURATION TEMPLATE
3
+ // Generated by MORPH Framework
4
+ // ============================================================
5
+
6
+ using System.ComponentModel.DataAnnotations.Schema;
7
+ using Microsoft.EntityFrameworkCore;
8
+ using Microsoft.EntityFrameworkCore.Metadata.Builders;
9
+ using Pgvector;
10
+
11
+ #nullable disable
12
+
13
+ namespace {{NAMESPACE}}.Domain.Entities;
14
+
15
+ /// <summary>
16
+ /// Entity with vector embedding for similarity search via pgvector.
17
+ /// Dimensions: 1536 (text-embedding-3-small). Adjust if using a different model.
18
+ /// </summary>
19
+ public class {{pascalCase FEATURE_NAME}}
20
+ {
21
+ public Guid Id { get; set; }
22
+ public string Title { get; set; } = string.Empty;
23
+ public string Content { get; set; } = string.Empty;
24
+ public string? Metadata { get; set; }
25
+
26
+ [Column(TypeName = "vector(1536)")]
27
+ public Vector? Embedding { get; set; }
28
+
29
+ public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
30
+ public DateTimeOffset? UpdatedAt { get; set; }
31
+ }
32
+
33
+ // ============================================================
34
+ // ENTITY TYPE CONFIGURATION
35
+ // ============================================================
36
+
37
+ namespace {{NAMESPACE}}.Infrastructure.Data.Configurations;
38
+
39
+ public class {{pascalCase FEATURE_NAME}}Configuration : IEntityTypeConfiguration<{{pascalCase FEATURE_NAME}}>
40
+ {
41
+ public void Configure(EntityTypeBuilder<{{pascalCase FEATURE_NAME}}> builder)
42
+ {
43
+ builder.ToTable("{{snakeCase FEATURE_NAME}}s");
44
+ builder.HasKey(e => e.Id);
45
+ builder.Property(e => e.Id).HasDefaultValueSql("gen_random_uuid()");
46
+ builder.Property(e => e.Title).IsRequired().HasMaxLength(200);
47
+ builder.Property(e => e.Content).IsRequired();
48
+ builder.Property(e => e.Metadata).HasColumnType("jsonb");
49
+ builder.Property(e => e.Embedding).HasColumnType("vector(1536)");
50
+ builder.Property(e => e.CreatedAt).HasDefaultValueSql("now()");
51
+
52
+ // HNSW index for cosine similarity search
53
+ builder.HasIndex(e => e.Embedding)
54
+ .HasMethod("hnsw")
55
+ .HasOperators("vector_cosine_ops")
56
+ .HasStorageParameter("m", 16)
57
+ .HasStorageParameter("ef_construction", 64);
58
+
59
+ builder.HasIndex(e => e.Title);
60
+ }
61
+ }
62
+
63
+ // ============================================================
64
+ // SETUP INSTRUCTIONS
65
+ // ============================================================
66
+ //
67
+ // 1. Install NuGet packages:
68
+ //
69
+ // dotnet add package Pgvector.EntityFrameworkCore
70
+ // dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
71
+ //
72
+ // 2. Configure NpgsqlDataSource with vector support in Program.cs:
73
+ //
74
+ // builder.Services.AddNpgsql<AppDbContext>(
75
+ // connectionString,
76
+ // npgsqlOptions => npgsqlOptions.UseVector());
77
+ //
78
+ // 3. Register in DbContext:
79
+ //
80
+ // public DbSet<{{pascalCase FEATURE_NAME}}> {{pascalCase FEATURE_NAME}}s => Set<{{pascalCase FEATURE_NAME}}>();
81
+ //
82
+ // protected override void OnModelCreating(ModelBuilder modelBuilder)
83
+ // {
84
+ // modelBuilder.HasPostgresExtension("vector");
85
+ // modelBuilder.ApplyConfiguration(new {{pascalCase FEATURE_NAME}}Configuration());
86
+ // }
87
+ //
88
+ // 4. Create and apply migration:
89
+ //
90
+ // dotnet ef migrations add Add{{pascalCase FEATURE_NAME}}WithVector -p src/{{NAMESPACE}}.Infrastructure -s src/{{NAMESPACE}}.Web
91
+ // dotnet ef database update -p src/{{NAMESPACE}}.Infrastructure -s src/{{NAMESPACE}}.Web
92
+ //
93
+ // ============================================================
@@ -5,7 +5,7 @@ namespace {{pascalCase PROJECT_NAME}}.Features.{{pascalCase FEATURE_NAME}}Featur
5
5
 
6
6
  internal sealed class {{pascalCase SLICE_NAME}}Endpoint : IApiEndpoint
7
7
  {
8
- public void MapEndpoint(WebApplication app)
8
+ public void MapEndpoint(IEndpointRouteBuilder app)
9
9
  {
10
10
  app.MapPost("{{kebabCase FEATURE_NAME}}s", async (IHandler<{{pascalCase SLICE_NAME}}Request, Result<{{pascalCase SLICE_NAME}}Response>> handler, {{pascalCase SLICE_NAME}}Request command, CancellationToken cancellationToken) =>
11
11
  {
@@ -1,9 +1,8 @@
1
1
  -- ============================================================
2
2
  -- Migration: {{titleCase FEATURE_NAME}}
3
- -- Stack: Next.js + Supabase
3
+ -- Stack: Next.js + Neon
4
4
  -- Generated by MORPH Framework
5
5
  -- Date: {{DATE}}
6
- -- Run: supabase db push
7
6
  -- ============================================================
8
7
 
9
8
  -- ============================================================
@@ -12,7 +11,7 @@
12
11
 
13
12
  create table if not exists public.{{TABLE_NAME}} (
14
13
  id uuid primary key default gen_random_uuid(),
15
- user_id uuid not null references auth.users(id) on delete cascade,
14
+ user_id text not null,
16
15
  name text not null,
17
16
  status text not null default 'draft'
18
17
  check (status in ('draft', 'active', 'completed', 'archived', 'failed', 'cancelled')),
@@ -66,35 +65,27 @@ create trigger set_{{TABLE_NAME}}_updated_at
66
65
  -- Enable RLS
67
66
  alter table public.{{TABLE_NAME}} enable row level security;
68
67
 
69
- -- Users can read their own rows
68
+ -- Users can read their own rows (Clerk JWT)
70
69
  create policy "Users can read own {{TABLE_NAME}}"
71
70
  on public.{{TABLE_NAME}}
72
71
  for select
73
- using (auth.uid() = user_id);
72
+ using (current_setting('request.jwt.claims')::json->>'sub' = user_id);
74
73
 
75
74
  -- Users can insert rows for themselves
76
75
  create policy "Users can insert own {{TABLE_NAME}}"
77
76
  on public.{{TABLE_NAME}}
78
77
  for insert
79
- with check (auth.uid() = user_id);
78
+ with check (current_setting('request.jwt.claims')::json->>'sub' = user_id);
80
79
 
81
80
  -- Users can update their own rows
82
81
  create policy "Users can update own {{TABLE_NAME}}"
83
82
  on public.{{TABLE_NAME}}
84
83
  for update
85
- using (auth.uid() = user_id)
86
- with check (auth.uid() = user_id);
84
+ using (current_setting('request.jwt.claims')::json->>'sub' = user_id)
85
+ with check (current_setting('request.jwt.claims')::json->>'sub' = user_id);
87
86
 
88
87
  -- Users can delete their own rows
89
88
  create policy "Users can delete own {{TABLE_NAME}}"
90
89
  on public.{{TABLE_NAME}}
91
90
  for delete
92
- using (auth.uid() = user_id);
93
-
94
- -- ============================================================
95
- -- 5. GRANTS
96
- -- ============================================================
97
-
98
- -- Grant access to authenticated users (via Supabase API)
99
- grant select, insert, update, delete on public.{{TABLE_NAME}} to authenticated;
100
- grant usage on schema public to authenticated;
91
+ using (current_setting('request.jwt.claims')::json->>'sub' = user_id);
@@ -19,7 +19,7 @@ create table if not exists public.{{TABLE_NAME}} (
19
19
  is_active boolean default true not null,
20
20
 
21
21
  -- Foreign keys (example)
22
- -- user_id uuid references auth.users(id) on delete cascade,
22
+ -- user_id text not null,
23
23
 
24
24
  -- Timestamps
25
25
  created_at timestamptz default now() not null,
@@ -70,30 +70,27 @@ create policy "{{TABLE_NAME}}_select_policy"
70
70
  on public.{{TABLE_NAME}} for select
71
71
  using (true);
72
72
 
73
- -- Policy: Users can only insert their own records (example)
73
+ -- Policy: Users can only insert their own records (Clerk JWT)
74
74
  -- create policy "{{TABLE_NAME}}_insert_policy"
75
75
  -- on public.{{TABLE_NAME}} for insert
76
- -- with check (auth.uid() = user_id);
76
+ -- with check (current_setting('request.jwt.claims')::json->>'sub' = user_id);
77
77
 
78
- -- Policy: Users can only update their own records (example)
78
+ -- Policy: Users can only update their own records (Clerk JWT)
79
79
  -- create policy "{{TABLE_NAME}}_update_policy"
80
80
  -- on public.{{TABLE_NAME}} for update
81
- -- using (auth.uid() = user_id)
82
- -- with check (auth.uid() = user_id);
81
+ -- using (current_setting('request.jwt.claims')::json->>'sub' = user_id)
82
+ -- with check (current_setting('request.jwt.claims')::json->>'sub' = user_id);
83
83
 
84
- -- Policy: Users can only delete their own records (example)
84
+ -- Policy: Users can only delete their own records (Clerk JWT)
85
85
  -- create policy "{{TABLE_NAME}}_delete_policy"
86
86
  -- on public.{{TABLE_NAME}} for delete
87
- -- using (auth.uid() = user_id);
87
+ -- using (current_setting('request.jwt.claims')::json->>'sub' = user_id);
88
88
 
89
- -- Policy: Admins have full access (example)
89
+ -- Policy: Admins have full access (Clerk JWT)
90
90
  -- create policy "{{TABLE_NAME}}_admin_policy"
91
91
  -- on public.{{TABLE_NAME}} for all
92
92
  -- using (
93
- -- exists (
94
- -- select 1 from public.user_roles
95
- -- where user_id = auth.uid() and role = 'admin'
96
- -- )
93
+ -- current_setting('request.jwt.claims')::json->>'role' = 'admin'
97
94
  -- );
98
95
 
99
96
  -- ========================================
@@ -1,6 +1,6 @@
1
1
  -- ============================================================
2
2
  -- RLS Policy: {{titleCase FEATURE_NAME}}
3
- -- Stack: Next.js + Supabase
3
+ -- Stack: Next.js + Neon
4
4
  -- Generated by MORPH Framework
5
5
  -- Date: {{DATE}}
6
6
  -- ============================================================
@@ -42,16 +42,16 @@ create policy "{{POLICY_NAME}}_delete"
42
42
  -- ============================================================
43
43
  -- Common USING / WITH CHECK expressions:
44
44
  --
45
- -- Owner-based:
46
- -- auth.uid() = user_id
45
+ -- Owner-based (Clerk JWT):
46
+ -- current_setting('request.jwt.claims')::json->>'sub' = user_id
47
47
  --
48
- -- Role-based:
49
- -- auth.jwt() ->> 'role' = 'admin'
48
+ -- Role-based (Clerk JWT):
49
+ -- current_setting('request.jwt.claims')::json->>'role' = 'admin'
50
50
  --
51
- -- Organization-based:
52
- -- org_id in (select org_id from public.org_members where user_id = auth.uid())
51
+ -- Organization-based (Clerk JWT):
52
+ -- org_id = (current_setting('request.jwt.claims')::json->>'org_id')
53
53
  --
54
54
  -- Public read, owner write:
55
55
  -- SELECT using (true)
56
- -- INSERT/UPDATE/DELETE using (auth.uid() = user_id)
56
+ -- INSERT/UPDATE/DELETE using (current_setting('request.jwt.claims')::json->>'sub' = user_id)
57
57
  -- ============================================================